一、什么是Atrribute
首先,咱们确定Attribute是一个类,下面是msdn文档对它的描述:
公共语言运行时容许你添加相似关键字的描述声明,叫作attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据保存在一块儿,能够用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。html
在.NET中,Attribute被用来处理多种问题,好比序列化、程序的安全特征、防止即时编译器对程序代码进行优化从而代码容易调试等等。下面,咱们先来看几个在.NET中标准的属性的使用,稍后咱们再回过头来讨论Attribute这个类自己。(文中的代码使用C#编写,但一样适用全部基于.NET的全部语言) 数组
三、Attribute类
除了.NET提供的那些Attribute派生类以外,咱们能够自定义咱们本身的Attribute,全部自定义的Attribute必须从Attribute类派生。如今咱们来看一下Attribute 类的细节: 安全
protected Attribute(): 保护的构造器,只能被Attribute的派生类调用。ide
三个静态方法:函数
static Attribute GetCustomAttribute():这个方法有8种重载的版本,它被用来取出施加在类成员上指定类型的Attribute。 工具
static Attribute[] GetCustomAttributes(): 这个方法有16种重载版本,用来取出施加在类成员上指定类型的Attribute数组。 post
static bool IsDefined():由八种重载版本,看是否指定类型的定制attribute被施加到类的成员上面。优化
实例方法:this
bool IsDefaultAttribute(): 若是Attribute的值是默认的值,那么返回true。 url
bool Match():代表这个Attribute实例是否等于一个指定的对象。
公共属性: TypeId: 获得一个惟一的标识,这个标识被用来区分同一个Attribute的不一样实例。
咱们简单地介绍了Attribute类的方法和属性,还有一些是从object继承来的。这里就不列出来了。
下面介绍如何自定义一个Attribute: 自定义一个Attribute并不须要特别的知识,其实就和编写一个类差很少。自定义的Attribute必须直接或者间接地从Attribute这个类派生,如:
public MyCustomAttribute : Attribute { ... }
这里须要指出的是Attribute的命名规范,也就是你的Attribute的类名+"Attribute",当你的Attribute施加到一个程序的元素上的时候,编译器先查找你的Attribute的定义,若是没有找到,那么它就会查找“Attribute名称"+Attribute的定义。若是都没有找到,那么编译器就报错。
四、定义或控制特性的使用
对于一个自定义的Attribute,你能够经过AttributeUsage的Attribute来限定你的Attribute 所施加的元素的类型。代码形式以下:
[AttriubteUsage(参数设置)] public 自定义Attribute : Attribute { ... }
做为参数的AttributeTarges的值容许经过“或”操做来进行多个值得组合,若是你没有指定参数,那么默认参数就是All 。 AttributeUsage除了继承Attribute 的方法和属性以外,还定义了如下三个属性:
AllowMultiple: 读取或者设置这个属性,表示是否能够对一个程序元素施加多个Attribute 。
Inherited:读取或者设置这个属性,表示是否施加的Attribute 能够被派生类继承或者重载。
ValidOn: 读取或者设置这个属性,指明Attribute 能够被施加的元素的类型。
下面让咱们来作一些实际的东西。咱们将会在Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
先让咱们来看一下AttributeTargets.Class。它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:
[Help("this is a do-nothing class")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
编译器报告错误以下:
AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.
咱们可使用AttributeTargets.All来容许Help特性被放置在任何程序实体前。可能的值是:
Assembly,Module,Class,Struct,Enum,Constructor,Method,Property,Field,Event,Interface,
Parameter,Delegate。
All = Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,
ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )
下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置屡次。
[Help("this is a do-nothing class")]
[Help("it contains a do-nothing method")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
它产生了一个编译期错误。
AnyClass.cs: Duplicate 'Help' attribute
Ok,如今咱们来讨论一下最后的这个属性。Inherited, 代表当特性被放置在一个基类上时,它可否被派生类所继承。
[Help("BaseClass")]
public class Base
{
}
public class Derive : Base
{
}
这里会有四种可能的组合:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]
第一种状况:
若是咱们查询(Query)(稍后咱们会看到如何在运行期查询一个类的特性)Derive类,咱们将会发现Help特性并不存在,由于inherited属性被设置为false。
第二种状况:
和第一种状况相同,由于inherited也被设置为false。
第三种状况:
为了解释第三种和第四种状况,咱们先来给派生类添加点代码:
[Help("BaseClass")]
public class Base
{
}
[Help("DeriveClass")]
public class Derive : Base
{
}
如今咱们来查询一下Help特性,咱们只能获得派生类的属性,由于inherited被设置为true,可是AllowMultiple却被设置为false。所以基类的Help特性被派生类Help特性覆盖了。
第四种状况:
在这里,咱们将会发现派生类既有基类的Help特性,也有本身的Help特性,由于AllowMultiple被设置为true。
属性与程序元素关联后,可使用反射查询属性存在及其值。查询属性的主要反射方法包含在 System.Reflection.MemberInfo 类(GetCustomAttributes 方法族)中。下面的示例演示使用反射获取对属性的访问的基本方法:
System.Reflection.MemberInfo info = typeof(Help);
object[] attributes = info.GetCustomAttributes(true);
for (int i = 0; i < attributes.Length; i++)
{
System.Console.WriteLine(attributes[i]);
}
出处:http://www.cnblogs.com/luckdv/articles/Atrribute.html