一、什麼是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