C#特性

1、什麼是Atrribute
首先,我們肯定Attribute是一個類,下面是msdn文檔對它的描述:
公 共語言運行時允許你添加類似關鍵字的描述聲明,叫做attributes, 它對程序中的元素進行標註,如類型、字段、方法和屬性等。Attributes和Microsoft .NET Framework文件的元數據保存在一起,可以用來向運行時描述你的代碼,或者在程序運行的時候影響應用程序的行爲。

在.NET中,Attribute被用來處理多種問題,比如序列化、程序的安全特徵、防止即時編譯器對程序代碼進行優化從而代碼容易調試等等。下 面,我們先來看幾個在.NET中標準的屬性的使用,稍後我們再回過頭來討論Attribute這個類本身。(文中的代碼使用C#編寫,但同樣適用所有基 於.NET的所有語言)

 

3、Attribute類
除了.NET提供的那些Attribute派生類之外,我們可以自定義我們自己的Attribute,所有自定義的Attribute必須從Attribute類派生。現在我們來看一下Attribute 類的細節:

protected Attribute(): 保護的構造器,只能被Attribute的派生類調用。

三個靜態方法:

static Attribute GetCustomAttribute(): 這個方法有8種重載的版本,它被用來取出施加在類成員上指定類型的Attribute。

static Attribute[] GetCustomAttributes(): 這個方法有16種重載版本,用來取出施加在類成員上指定類型的Attribute數組。

static bool IsDefined(): 由八種重載版本,看是否指定類型的定製attribute被施加到類的成員上面。

 

實例方法:

bool IsDefaultAttribute(): 如果Attribute的值是默認的值,那麼返回true。

bool Match():表明這個Attribute實例是否等於一個指定的對象。

 

公共屬性: TypeId: 得到一個唯一的標識,這個標識被用來區分同一個Attribute的不同實例。

我們簡單地介紹了Attribute類的方法和屬性,還有一些是從object繼承來的。這裏就不列出來了。

下面介紹如何自定義一個Attribute: 自定義一個Attribute並不需要特別的知識,其實就和編寫一個類差不多。自定義的Attribute必須直接或者間接地從Attribute這個類派生,如:

public MyCustomAttribute : Attribute { ... }

這裏需要指出的是Attribute的命名規範,也就是你的Attribute的類名+"Attribute",當你的Attribute施加到一 個程序的元素上的時候,編譯器先查找你的Attribute的定義,如果沒有找到,那麼它就會查找“Attribute名稱"+Attribute的定 義。如果都沒有找到,那麼編譯器就報錯。

 

4、定義或控制特性的使用

對於一個自定義的Attribute,你可以通過AttributeUsage的Attribute來限定你的Attribute 所施加的元素的類型。代碼形式如下:
[AttriubteUsage(參數設置)] public 自定義Attribute : Attribute { ... }

作爲參數的AttributeTarges的值允許通過“或”操作來進行多個值得組合,如果你沒有指定參數,那麼默認參數就是All 。 AttributeUsage除了繼承Attribute 的方法和屬性之外,還定義了以下三個屬性:

AllowMultiple : 讀取或者設置這個屬性,表示是否可以對一個程序元素施加多個Attribute 。

Inherited :讀取或者設置這個屬性,表示是否施加的Attribute 可以被派生類繼承或者重載。

ValidOn : 讀取或者設置這個屬性,指明Attribute 可以被施加的元素的類型。

 

下面讓我們來做一些實際的東西。我們將會在Help特性前放置AttributeUsage特性以期待在它的幫助下控制Help特性的使用。

  1. [AttributeUsage
    (AttributeTargets
    .Class, AllowMultiple = false
    , Inherited = false
    )]
    
  2. public class 
    HelpAttribute 
    : Attribute
    
    
  3. {
    
  4.     public 
    HelpAttribute(String 
    Description_in)
    
  5.     {
    
  6.         this
    .description = Description_in;
    
  7.     }
    
  8.     protected 
    String 
    description;
    
  9.     public 
    String 
    Description
    
  10.     {
    
  11.         get
    
    
  12.         
    {
    
  13.             return this
    .description;
    
  14.         }
    
  15.     }
    
  16. }
    

 

 

代碼討論

  • 屬性 AttributeUsage 指定該屬性可以應用於的語言元素。
  • 屬性類是從 System.Attribute 派生的公共類,至少有一個公共構造函數。
  • 屬性類有兩種類型的參數:
    •       “定位參數”,每次使用屬性時都必須指定這些參數。定位參數被指定爲屬性類的構造函數參數。在上面的示例中,url 便是一個定位參數。
    •      “命名參數”,可選。如果使用屬性時指定了命名參數,則必須使用參數的名稱。通過包含非靜態字段或屬性來定義命名參數。在上面的示例中,Topic 便是一個命名參數。

 

先讓我們來看一下AttributeTargets.Class 。它規定了Help特性只能被放在class的前面。這也就意味着下面的代碼將會產生錯誤:

  1. [Help
    ("this is a do-nothing class"
    )]
    
  2. public class 
    AnyClass
    
    
  3. {
    
  4.     [Help
    ("this is a do-nothing method"
    )] //error 
    
    
  5.     
    public void 
    AnyMethod()
    
  6.     {
    
  7.     }
    
  8. }
    

 

 

 

編譯器報告錯誤如下:

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。它規定了特性不能被重複放置多次。

  1. [Help
    ("this is a do-nothing class"
    )]
    
  2. [Help
    ("it contains a do-nothing method"
    )]
    
  3. public class 
    AnyClass
    
    
  4. {
    
  5.     [Help
    ("this is a do-nothing method"
    )] //error 
    
    
  6.     
    public void 
    AnyMethod()
    
  7.     {
    
  8.     }
    
  9. }
    

 

 

它產生了一個編譯期錯誤。

AnyClass.cs: Duplicate 'Help' attribute

Ok,現在我們來討論一下最後的這個屬性。Inherited, 表明當特性被放置在一個基類上時,它能否被派生類所繼承。

  1. [Help
    ("BaseClass"
    )]
    
  2. public class 
    Base
    
    
  3. {
    
  4. }
    
  5. public class 
    Derive 
    : Base
    
    
  6. {
    
  7. }
    

 

 

 

 

這裏會有四種可能的組合:

[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。

第三種情況:

爲了解釋第三種和第四種情況,我們先來給派生類添加點代碼:

  1. [Help
    ("BaseClass"
    )]
    
  2. public class 
    Base
    
    
  3. {
    
  4. }
    
  5. [Help
    ("DeriveClass"
    )]
    
  6. public class 
    Derive 
    : Base
    
    
  7. {
    
  8. }
    

現在我們來查詢一下Help特性,我們只能得到派生類的屬性,因爲inherited被設置爲true,但是AllowMultiple卻被設置爲false。因此基類的Help特性被派生類Help特性覆蓋了。

第四種情況:

在這裏,我們將會發現派生類既有基類的Help特性,也有自己的Help特性,因爲AllowMultiple被設置爲true。

  •  
    •  
        • 通過反射訪問屬性

    屬性與程序元素關聯後,可以使用反射查詢屬性存在及其值。查詢屬性的主要反射方法包含在 System.Reflection.MemberInfo 類(GetCustomAttributes 方法族)中。下面的示例演示使用反射獲取對屬性的訪問的基本方法:

    1. System.Reflection.MemberInfo 
      info = typeof
      (Help);
      
    2. object
      [] attributes = info.GetCustomAttributes(true
      );
      
    3. for 
      (int 
      i = 0; i < attributes.Length; i++)
      
    4. {
      
    5.     System.Console
      .WriteLine(attributes[i]);
      
    6. } 
    本文轉載自:http://www.cnblogs.com/luckdv/articles/1682488.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章