自定义特性
应用特性的语法和之前见过的其他语法很不相同。你可能会觉得特性跟结构是完全不同的类型,其实不是,特性只是某个特殊结构的类。所有的特性类都派生自System.Attribute。
声明自定义特性
声明一个特性类和声明其他类一样。有下面的注意事项
声明一个派生自System.Attribute的类 给它起一个以后缀Attribute结尾的名字 (安全起见,一般我们声明一个sealed的特性类)
特性类声明如下:
public sealed class MyAttributeAttribute : System.Attribute{
...
特性类的公共成员可以是
字段 属性 构造函数
构造函数
特性类的构造函数的声明跟普通类一样,如果不写系统会提供一个默认的,可以进行重载
构造函数的调用
[MyAttribute("a value")] //调用特性类的带有一个字符串的构造函数
[MyAttribute("Version 2.3","Mackel")] //调用特性类带有两个字符串的构造函数
构造函数的实参,必须是在编译期间能确定值的常量表达式
如果调用的是无参的构造函数,那么后面的()可以不写
构造函数中的位置参数和命名参数
public sealed class MyAttributeAttribute:System.Attribute{
public string Description;
public string Ver;
public string Reviewer;
public MyAttributeAttribute(string desc){
Description = desc;
}
}
//位置参数(按照构造函数中参数的位置)
//命名参数,按照属性的名字进行赋值
[MyAttribute("An excellent class",Reviewer = "Amy McArthur",Ver="3.12.3")]
限定特性的使用
有一个很重要的预定义特性可以用来应用到自定义特性上,那就是AttributeUsage特性,我们可以使用它来限制特性使用在某个目标类型上。
例如,如果我们希望自定义特性MyAttribute只能应用到方法上,那么可以用如下形式使用AttributeUsate:
[AttributeUsage(AttributeTarget.Method)]
public sealed class MyAttributeAttribute : System.Attribute{
...
AttributeUsage有是三个重要的公共属性如下:
ValidOn 保存特性能应用到的目标类型的列表,构造函数的第一个参数就是AttributeTarget 类型的枚举值 Inherited 一个布尔值,它指示特性是否会被特性类所继承 默认为true AllowMutiple 是否可以多个特性的实例应用到一个目标上 默认为false
AttributeTarget枚举的成员
All Assembly Class Constructor Delegate Enum Event Field
GenericParameter Interface Method Module Parameter Property
ReturnValue Struct
多个参数之间使用按位或|运算符来组合
AttributeTarget.Method|AttributeTarget.Constructor
自定义特性一般遵守的规范
特性类应该表示目标结构的一些状态
如果特性需要某些字段,可以通过包含具有位置参数的构造函数来收集数据,可选字段可以采用命名参数按需初始化
除了属性之外,不要实现公共方法和其他函数成员
为了更安全,把特性类声明为sealed
在特性声明中使用AttributeUsage来指定特性目标组
案例:
[AttributeUsage(AttributeTarget.Class)]
public sealed class ReviewCommentAttribute:System.Attribute{
public string Description{get;set;}
public string VersionNumber{get;set;}
public string ReviewerID{get;set;}
public ReviewerCommentAttribute(string desc,string ver){
Description = desc;
VersionNumber = ver;
}
}
访问特性(消费特性)
1.我们可以使用IsDefined方法来,通过Type对象可以调用这个方法,来判断这个类上是否应用了某个特性
bool isDefined = t.IsDefined( typeof(AttributeClass),false )
第一个参数是传递的需要检查的特性的Type对象
第二个参数是一个bool类型的,表示是否搜索AttributeClass的继承树
2.
object[] attArray = t.GetCustomAttributes(false);
它返回的是一个object的数组,我们必须将它强制转换成相应类型的特性类型
bool的参数指定了它是否搜索继承树来查找特性
调用这个方法后,每一个与目标相关联的特性的实例就会被创建