特性(Attribute):
用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。我们可以通过使用特性向程序添加声明性信息。特性是通过放置在它所应用的元素前面的方括号([ ])来应用的,如[Table(“UserInfos”)]。
.Net 框架提供了两种类型的特性:预定义特性和自定义特性。
特性语法与预定义特性:
应用语法:
[特性名(参数1, 参数2 = 值, …)]
应用元素
.Net 框架提供了三种预定义特性:
AttributeUsage 如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
Conditional 标记了一个条件方法,其执行依赖于指定的预处理标识符。
Obsolete 标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。
自定义特性:
Net 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。
创建并使用自定义特性包含四个步骤:
1.声明自定义特性 ------特性名一般规定以Attribute结尾,派生于Attribute
2.构建自定义特性 ------定义属性或字段,创建构造函数、指定应用目标
//定义了一个特性类 命名方式:特性名+Attribute
//特性:加注释
//步骤1:定义特性类
//步骤2:构建自定义特性 ----属性、构造函数、应用目标
[AttributeUsage(AttributeTargets.Property|AttributeTargets.Class|AttributeTargets.Field)]//指定应用目标:属性、类、字段
public class RemarkAttribute:Attribute
{
public string Description { get; set; }
public RemarkAttribute(string desp)
{
Description = desp;
}
}
public class RequireAttribute:Attribute
{
public bool isRequired = false;
}
其中AttributeUsage是一个C#中的特性类,它用于指定另一个自定义特性类如何被使用。AttributeUsage类的实例可以用作自定义特性类的参数,以确定该特性可以用于哪些目标。
AttributeUsage类的构造函数有三个参数:
validOn:指定该特性可以用于哪些目标,包括类、方法、属性等等。该参数使用AttributeTargets枚举类型。
AllowMultiple:指定是否允许将该特性应用于同一目标多次。如果为true,则允许多个实例共同存在;否则,如果尝试在同一目标上多次应用该特性,则会引发异常。
Inherited:指定该特性是否可继承。如果为true,则允许派生类继承该特性;否则,不允许。
常用的AttributeUsage属性及其含义如下:
AttributeTargets:指定该特性可以应用于哪些元素。常用的值有:类、结构、枚举、方法、属性、字段等等。
AllowMultiple:指定是否允许将该特性应用于同一目标多次。如果为true,则允许多个实例共同存在;否则,如果尝试在同一目标上多次应用该特性,则会引发异常。
Inherited:指定该特性是否可继承。如果为true,则允许派生类继承该特性;否则,不允许。
示例代码:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
public class MyAttribute : Attribute
{
// code
}
在这个示例中,MyAttribute类指定了它可以应用于类和方法,允许多个实例共同存在,但不允许派生类继承。
3.在目标程序元素上应用自定义特性 [特性名(参数值)]
[Remark("收入信息")]
public class IncomeInfo
{
[Remark("名目")]
[Require(isRequired =true)]
public string ItemName { get; set; }
[Remark("描述")]
[Require(isRequired = false)]
public string Remark { get; set; }
[Remark("收入金额")]
public decimal Amount { get; set; }
}
4.通过反射访问特性
public static string GetClassDescription<T>()
{
string desp = null;
Type type = typeof(T);
//获取应用在类上的Remark特性对象
RemarkAttribute attr =type.GetCustomAttribute<RemarkAttribute>();
if (attr != null)
{
desp = attr.Description;
}
return desp;
}
通过GetCustomAttribute便可以获取到我们上面声明的特性对象,存储在desp中返回。
最后一个步骤需要编写一个简单的程序来读取元数据以便查找各种特性。
该程序——使用反射来在运行时访问特性。
特性在这里的使用就好比注释,不过注释并不会影响程序的代码执行,但是特性通过反射的方式可以影响代码的执行。