自定义特性

应用特性的语法和之前见过的其他语法很不相同。你可能会觉得特性跟结构是完全不同的类型,其实不是,特性只是某个特殊结构的类。所有的特性类都派生自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的参数指定了它是否搜索继承树来查找特性

调用这个方法后,每一个与目标相关联的特性的实例就会被创建

results matching ""

    No results matching ""