13.C# 特性[摘自網路]

isongoo發表於2008-05-05

    http://blog.csdn.net/ojekleen/archive/2007/09/18/1789673.aspx

    特性(Attributes)是一種嶄新的宣告性資訊。我們不僅可以透過特性來定義設計層面的資訊(例如help file, URL for documentation)以及執行時(run-time)資訊(例如使XML與class相聯絡),而且我們還可以利用特性建立自描述(self- describing)元件。在這篇教程中,我們將會看到如何建立和新增特性到各種程式實體以及如何在執行時環境中獲取特性資訊。
   定義
   正如MSDN中所描述的那樣-----  
   “特性是被指定給某一宣告的一則附加的宣告性資訊。”  
  使用預定義(Pre-defined)特性  
  在C#中,有一個小的預定義特性集合。在學習如何建立我們自己的定製特性(custom attributes)之前,我們先來看看在我們的程式碼中如何使用預定義特性。  
  using System;
  public class AnyClass
  {
   [Obsolete("Don't use Old method, use New method", true)]
   static void Old( ) { }  
   static void New( ) { }  
   public static void Main( )
   {
   Old( );
   }
  }
  我們先來看一下上面這個例子,在這個例子中我們使用了Obsolete特性,它標記了一個不應該再被使用的程式實體。第一個引數是一個字串,它解釋了為什麼該實體是過時的以及應該用什麼實體來代替它。實際上,你可以在這裡寫任何文字。第二個引數告訴編譯器應該把使用這個過時的程式實體當作 一種錯誤。它的預設值是false,也就是說編譯器對此會產生一個警告。  
  當我們嘗試編譯上面這段程式的時候,我們將會得到一個錯誤:  
  AnyClass.Old()' is obsolete: 'Don't use Old method, use New method'    
  開發定製特性(custom attributes) 
  現在讓我們來看看如何開發我們自己的特性。 
  首先我們要從System.Attribute派生出我們自己的特性類(一個從System.Attribute抽象類繼承而來的類,不管是直接還是間接繼承,都會成為一個特性類。特性類的宣告定義了一種可以被放置在宣告之上新的特性)。  
  using System;
  public class HelpAttribute : Attribute
  {
  }
  不管你是否相信,我們已經建立了一個定製特性,現在我們可以用它來裝飾現有的類就好像上面我們使用Obsolete attribute一樣。  
  [Help()]
  public class AnyClass
  {
  }
  注意:對一個特性類名使用Attribute字尾是一個慣例。然而,當我們把特性新增到一個程式實體,是否包括Attribute字尾是我們 的自由。編譯器會首先在System.Attribute的派生類中查詢被新增的特性類。如果沒有找到,那麼編譯器會新增Attribute字尾繼續查 找。  
  到目前為止,這個特性還沒有起到什麼作用。下面我們來新增些東西給它使它更有用些。  
  using System;
  public class HelpAttribute : Attribute
  {
   public HelpAttribute(String Descrition_in)
   {
   this.description = Description_in;
   }
   protected String description;
   public String Description
   {
   get
   {
   return this.description;  
   }
   }
  }
  [Help("this is a do-nothing class")]
  public class AnyClass
  {
  }
  在上面的例子中,我們給HelpAttribute特性類新增了一個屬性並且在後續的部分中我們會在執行時環境中查尋它。
     定義或控制特性的使用  

 AttributeUsage類是另外一個預定義特性類,它幫助我們控制我們自己的定製特性的使用。它描述了一個定製特性如和被使用。  
  AttributeUsage
有三個屬性,我們可以把它放置在定製屬性前面。第一個屬性是:  
  ValidOn  
  
透過這個屬性,我們能夠定義定製特性應該在何種程式實體前放置。一個屬性可以被放置的所有程式實體在AttributeTargets enumerator中列出。透過OR操作我們可以把若干個AttributeTargets值組合起來。  
  AllowMultiple  
  
這個屬性標記了我們的定製特效能否被重複放置在同一個程式實體前多次。 
  Inherited  
  
我們可以使用這個屬性來控制定製特性的繼承規則。它標記了我們的特效能否被繼承。  
  
下面讓我們來做一些實際的東西。我們將會在剛才的Help特性前放置AttributeUsage特性以期待在它的幫助下控制Help特性的使用。  
  using System;
  [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

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/725190/viewspace-260438/,如需轉載,請註明出處,否則將追究法律責任。

相關文章