中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#中如何使用Attributes

發布時間:2021-12-01 11:33:31 來源:億速云 閱讀:171 作者:小新 欄目:編程語言

這篇文章主要為大家展示了“C#中如何使用Attributes”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“C#中如何使用Attributes”這篇文章吧。

C# Attributes介紹

Attributes是一種新的描述信息,我們既可以使用attributes來定義設計期信息(例如 幫助文件,文檔的URL),還可以用attributes定義運行時信息(例如,使XML中的元素與類的成員字段關聯起來)。我們也可以用attributes來創建一個“自描述”的組件。

C# Attributes定義

MSDN 中做如下定義(ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsharpspec_17_2.htm)

"An attribute is a piece of additional declarative information that is specified for a declaration." 

使用預定義 Attributes

在c#中已有一小組預定義的attributes,在我們學習怎樣創建自定義attributes前,先來了解下在我們的代碼中使用那些預定義的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”attribute,它標記了一個不該再被使用的語言元素(譯者注:這里的元素為方法),該屬性的***個參數是string類型,它解釋為什么該元素被荒棄,以及我們該使用什么元素來代替它。實際中,我們可以書寫任何其它文本來代替這段文本。第二個參數是告訴編譯器把依然使用這被標識的元素視為一種錯誤,這就意味著編譯器會因此而產生一個警告。

當我們試圖編譯上面的上面的程序,我們會得到如下錯誤:

AnyClass.Old()' is obsolete: 'Don't use Old method,  use New method'

開發自定義Attributes

現在我們即將了解怎么開發自定義的attributes。這兒有個小小處方,有它我們就可以學會創建自定義的attributes。

在C#中,我們的attribute類都派生于System.Attribute類 (A class that derives from the abstract class System.Attribute, whether directly or indirectly, is an attribute class. The declaration of an attribute class defines a new kind of attribute that can be placed on a declaration) ,我們就這么行動吧。

using System;   public class HelpAttribute : Attribute   {   }

不管你是否相信我,就這樣我們就已經創建了一個自定義attribute。現在就可以用它來裝飾我們的類了,就像我們使用obsolete attribute一樣。

[Help()]   public class AnyClass   {   }

注意:按慣例我們是用”Attribute“作為attribute類名的后綴,然而,當我們當我們把attribute綁定到某語言元素時,是不包含“Attribute“后綴的。編譯器首先在System.Attribute 的繼承類中查找該attribute,如果沒有找到,編譯器會把“Attribute“追加到該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  {  }

在上面的例子中,我們在attribute類中添加了一個屬性,在***一節中,我們將在運行時查詢該屬性。

定義或控制自定義Attribute的用法

AttributeUsage 類是另一預定義類(譯者注:attribute類本身用這個atrribute System.AttributeUsage來標記),它將幫助我們控制我們自定義attribute的用法,這就是,我們能為自定義的attribute類定義attributes。

它描述了一個自定義attribute類能被怎樣使用。

AttributeUsage 提供三個屬性,我們能將它們放置到我們的自定義attribute類上, ***個特性是:

ValidOn

通過這個屬性,我們能指定我們的自定義attribute可以放置在哪些語言元素之上。這組我們能把自定義attribute類放置其上的語言元素被放在枚舉器AttributeTargets 中。我們可以使用bitwise(譯者注:這個詞不知道怎么翻譯好,但他的意思是可以這么用:[AttributeUsage((AttributeTargets)4, AllowMultiple = false, Inherited = false )],4代表就是“class”元素,其它諸如1代表“assembly”,16383代表“all”等等)或者”.”操做符綁定幾個AttributeTargets 值。(譯者注:默認值為AttributeTargets.All)

AllowMultiple

該屬性標識我們的自定義attribte能在同一語言元素上使用多次。(譯者注:該屬性為bool類型,默認值為false,意思就是該自定義attribute在同一語言元素上只能使用一次)

Inherited

我們可以使用該屬性來控制我們的自定義attribute類的繼承規則。該屬性標識我們的自定義attribute是否可以由派生類繼承。((譯者注:該屬性為bool類型,默認值為false,意思是不能繼承)

讓我們來做點實際的東西吧,我們將把AttributeUsage attribute 放置在我們的help attribute 上并在它的幫助下,我們來控制help attribute的用法。

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 attribute 只能放置在語言元素”class”之上。這就意味著,下面的代碼將會產生一個錯誤。

AnyClass.cs: Attribute 'Help' is not valid on this declaration type.

It is valid on 'class' declarations only.

現在試著把它綁定到方法。

[Help("this is a do-nothing class")]   public class AnyClass   {       [Help("this is a do-nothing method")]    //error       public void AnyMethod()       {       }   }

我們可以使用 AttributeTargets.All 來允許 Help attribute 可以放置在任何預定義的語言元素上,那些可能的語言元素如下: 

C#中如何使用Attributes

[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”, 指出當把該attribute放置于一個基類之上,是否派生類也繼承了該attribute。如果綁定至某個attribute類的”Inherited”被設為true,那么該attribute就會被繼承,然而如果綁定至某個attribute類的”Inherited”被設為false或者沒有定義,那么該attribute就不會被繼承。

讓我們假設有如下的類關系。

[Help("BaseClass")]    public class Base   {   }       public class Derive :  Base   {   }

我們有四種可能的綁定:

C#中如何使用Attributes

***種情況

如果我們查詢(我們將在后面來了解如何在運行時來查詢attributes)派生類中的help attribute,我們將不可能查詢到因為”Inherited”被設為了false。

第二種情況

第二種情況沒有什么不同,因為其”Inherited”也被設為了false。

第三種情況

為了解釋第三種和第四種情況,讓我們為派生類也綁定同一attribute。

[Help("BaseClass")]    public class Base   {   }   [Help("DeriveClass")]    public class Derive :  Base   {   }

現在我們查詢相關的help attribute ,我們將僅僅可以得到派生類的attribute,為什么這樣是因為help attribute雖然允許被繼承,但不能多次在同一語言元素上使用,所以基類中的help attribute被派生類的help attribute 重寫了。

第四種情況

在第四種情況中,當我們查詢派生類的help attribute 時,我們可以得到兩個attributes,當然是因為help attribute既允許被繼承,又允許在同一語言元素上多次使用的結果。

注意:AttributeUsage attribute 僅應用在那種是System.Attribute 派生的attriubte類而且綁定值該attriubte類的AllowMultiple和Inherited均為false上才是有效的。

可選參數 vs. 命名參數

可選參數是attribute類構造函數的參數。它們是強制的,必須在每次在attribute綁定至某語言元素時提供一個值。而另一方面,命名參數倒是真正的可選參數,不是在attribute構造函數的參數。

為了更加詳細的解釋,讓我們在Help類中添加另外的屬性。

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false,    Inherited = false)]   public class HelpAttribute : Attribute   {       public HelpAttribute(String Description_in)       {           this.description = Description_in;           this.verion = "No Version is defined for this class";       }       protected String description;       public String Description       {           get            {               return this.description;           }       }       protected String version;       public String Version       {           get            {               return this.version;           }           //if we ever want our attribute user to set this property,            //we must specify set method for it            set            {               this.verion = value;           }       }   }   [Help("This is Class1")]   public class Class1   {   }     [Help("This is Class2", Version = "1.0")]   public class Class2   {   }     [Help("This is Class3", Version = "2.0",     Description = "This is do-nothing class")]   public class Class3   {   }

當我們在Class1中查詢Help attribute已經它的屬性,我們將得到:

Help.Description : This is Class1

Help.Version :No Version is defined for this class

因為我們沒有為Version這個屬性定義任何任何值,所以在構造函數中設定的值被我們查詢出來了。如果沒有定義任何值,那么就會賦一個該類型的默認值(例如:如果是int型,默認值就是0)。

現在,查詢Class2的結果是:

Help.Description : This is Class2

Help.Version :  1.0

我們不能為了可選參數而使用多個構造函數,應該用已命名參數來代替。我們之所以稱它們為已命名的,是因為當我們在構造函數為它們提供值時,我們必須命名它們。例如,在第二個類中,我們如是定義Help。

[Help("This is Class2", Version = "1.0")]

在 AttributeUsage 例子中, 參數”ValidOn”是可選參數,而“Inherited“和“AllowMultiple“ 是命名參數。

注意:為了在attribute的構造函數中設定命名參數的值,我們必須為相應的屬性提供一個set方法否則會引起編譯期錯誤:

'Version' : Named attribute argument can't be a read only property

現在,我們在Class3中查找Help attribute 及其屬性會發生什么呢?結果是跟上面提到的相同的編譯期錯誤。

'Desciption' : Named attribute argument can't be a read only property

現在我們修改下Help類,為屬性”Description”加一個set方法。現在的輸出就是:

Help.Description : This is do-nothing class

Help.Version : 2.0

在屏幕后面究竟發生了什么呢?首先帶有可選參數的構造函數被調用,然后,每個命名參數的set方法被調用,在構造函數中賦給命名參數的值被set方法所覆寫。

參數類型

一個attribute類的參數類型被限定在如下類型中:

C#中如何使用Attributes 

Attributes 標記

假設,我們想把Help attribute 綁定至元素 assembly。***個問題是我們要把Help attribute 放在哪兒才能讓編譯器確定該attribute是綁定至整個assembly呢?考慮另一種情況,我們想把attribute綁定至一個方法的返回類型上,怎樣才能讓編譯器確定我們是把attribute綁定至方法的返回類型上,而不是整個方法呢?

為了解決諸如此類的含糊問題,我們使用attribute標識符,有了它的幫助,我們就可以確切地申明我們把attribute 綁定至哪一個語言元素。

例如:

[assembly: Help("this a do-nothing assembly")]

這個在Help attribute 前的assembly標識符確切地告訴編譯器,該attribute被綁定至整個assembly。可能的標識符有: 

C#中如何使用Attributes

在運行時查詢Attributes

現在我們明白怎么創建attribtes和把它們綁定至語言元素。是時候來學習類的使用者該如何在運行時查詢這信息。

為了查詢一語言元素上綁定的attributes,我們必須使用反射。反射有能力在運行時發現類型信息。

我們可以使用.NET Framework Reflection APIs 通過對整個assembly元數據的迭代,列舉出assembly中所有已定義的類,類型,還有方法。

記住那舊的Help attribute 和AnyClass 類。

using System;   using System.Reflection;   using System.Diagnostics;     //attaching Help attribute to entire assembly   [assembly : Help("This Assembly demonstrates custom attributes     creation and their run-time query.")]     //our custom attribute class   public class HelpAttribute : Attribute   {       public HelpAttribute(String Description_in)       {           //           // TODO: Add constructor logic here           this.description = Description_in;           //       }       protected String description;       public String Description       {           get            {               return this.deescription;                               }                   }       }   //attaching Help attribute to our AnyClass   [HelpString("This is a do-nothing Class.")]   public class AnyClass   {   //attaching Help attribute to our AnyMethod       [Help("This is a do-nothing Method.")]       public void AnyMethod()       {       }   //attaching Help attribute to our AnyInt Field       [Help("This is any Integer.")]       public int AnyInt;   }   class QueryApp   {       public static void Main()       {       }   }

我們將在接下來的兩節中在我們的Main方法中加入attribute查詢代碼。

查詢程序集的Attributes

在接下來的代碼中,我們先得到當前的進程名稱,然后用Assembly類中的LoadForm()方法加載程序集,再有用GetCustomAttributes()方法得到被綁定至當前程序集的自定義attributes,接下來用foreach語句遍歷所有attributes并試圖把每個attribute轉型為Help attribute(即將轉型的對象使用as關鍵字有一個優點,就是當轉型不合法時,我們將不需擔心會拋出異常,代之以空值(null)作為結果),接下來的一行就是檢查轉型是否有效,及是不是為空,跟著就顯示Help attribute的“Description”屬性。

class QueryApp   {       public static void Main()       {           HelpAttribute HelpAttr;            //Querying Assembly Attributes           String assemblyName;           Process p = Process.GetCurrentProcess();           assemblyName = p.ProcessName + ".exe";            Assembly a = Assembly.LoadFrom(assemblyName);            foreach (Attribute attr in a.GetCustomAttributes(true))          {               HelpAttr = attr as HelpAttribute;               if (null != HelpAttr)               {                   Console.WriteLine("Description of {0}:\n{1}",                                      assemblyName,HelpAttr.Description);               }           }   }   }

程序輸出如下:

Description of QueryAttribute.exe:

This Assembly demonstrates custom attributes creation and

their run-time query.

Press any key to continue

查詢類、方法、類成員的Attributes

下面的代碼中,我們惟一不熟悉的就是Main()方法中的***行。

Type type = typeof(AnyClass);

它用typeof操作符得到了一個與我們AnyClass類相關聯的Type型對象。剩下的查詢類attributes代碼就與上面的例子是相似的,應該不要解釋了吧(我是這么想的)。

為查詢方法和類成員的attributes,首先我們得到所有在類中存在的方法和成員,然后我們查詢與它們相關的所有attributes,這就跟我們查詢類attributes一樣的方式。

class QueryApp   {       public static void Main()       {             Type type = typeof(AnyClass);           HelpAttribute HelpAttr;               //Querying Class Attributes           foreach (Attribute attr in type.GetCustomAttributes(true))           {               HelpAttr = attr as HelpAttribute;               if (null != HelpAttr)               {                   Console.WriteLine("Description of AnyClass:\n{0}",                                      HelpAttr.Description);               }           }           //Querying Class-Method Attributes             foreach(MethodInfo method in type.GetMethods())           {               foreach (Attribute attr in method.GetCustomAttributes(true))               {                   HelpAttr = attr as HelpAttribute;                   if (null != HelpAttr)                   {                       Console.WriteLine("Description of {0}:\n{1}",                                          method.Name,                                          HelpAttr.Description);                   }               }           }           //Querying Class-Field (only public) Attributes           foreach(FieldInfo field in type.GetFields())           {               foreach (Attribute attr in field.GetCustomAttributes(true))               {                   HelpAttr= attr as HelpAttribute;                   if (null != HelpAttr)                   {                       Console.WriteLine("Description of {0}:\n{1}",                                         field.Name,HelpAttr.Description);                   }               }           }       }   }

以上是“C#中如何使用Attributes”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿合奇县| 满城县| 西青区| 大姚县| 福贡县| 镇康县| 修文县| 江陵县| 武义县| 伊金霍洛旗| 梨树县| 交口县| 茶陵县| 碌曲县| 清水河县| 天峨县| 扎兰屯市| 浠水县| 涞源县| 招远市| 隆昌县| 延安市| 桃园县| 车致| 霍州市| 佛冈县| 井研县| 丰原市| 美姑县| 永仁县| 苏州市| 定南县| 甘孜| 云安县| 长阳| 大理市| 南雄市| 靖远县| 施甸县| 宿州市| 冷水江市|