這篇文章主要為大家展示了“C#中如何使用Attributes”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“C#中如何使用Attributes”這篇文章吧。
創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比浉河網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式?jīng)负泳W(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋浉河地區(qū)。費用合理售后完善,10多年實體公司更值得信賴。
C# Attributes介紹
Attributes是一種新的描述信息,我們既可以使用attributes來定義設(shè)計期信息(例如 幫助文件,文檔的URL),還可以用attributes定義運行時信息(例如,使XML中的元素與類的成員字段關(guān)聯(lián)起來)。我們也可以用attributes來創(chuàng)建一個“自描述”的組件。
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."
使用預(yù)定義 Attributes
在c#中已有一小組預(yù)定義的attributes,在我們學(xué)習(xí)怎樣創(chuàng)建自定義attributes前,先來了解下在我們的代碼中使用那些預(yù)定義的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( ); } }
仔細(xì)看下該實例,在該實例中我們用到了”O(jiān)bsolete”attribute,它標(biāo)記了一個不該再被使用的語言元素(譯者注:這里的元素為方法),該屬性的***個參數(shù)是string類型,它解釋為什么該元素被荒棄,以及我們該使用什么元素來代替它。實際中,我們可以書寫任何其它文本來代替這段文本。第二個參數(shù)是告訴編譯器把依然使用這被標(biāo)識的元素視為一種錯誤,這就意味著編譯器會因此而產(chǎn)生一個警告。
當(dāng)我們試圖編譯上面的上面的程序,我們會得到如下錯誤:
AnyClass.Old()' is obsolete: 'Don't use Old method, use New method'
開發(fā)自定義Attributes
現(xiàn)在我們即將了解怎么開發(fā)自定義的attributes。這兒有個小小處方,有它我們就可以學(xué)會創(chuàng)建自定義的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 { }
不管你是否相信我,就這樣我們就已經(jīng)創(chuàng)建了一個自定義attribute?,F(xiàn)在就可以用它來裝飾我們的類了,就像我們使用obsolete attribute一樣。
[Help()] public class AnyClass { }
注意:按慣例我們是用”Attribute“作為attribute類名的后綴,然而,當(dāng)我們當(dāng)我們把a(bǔ)ttribute綁定到某語言元素時,是不包含“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類中添加了一個屬性,在***一節(jié)中,我們將在運行時查詢該屬性。
定義或控制自定義Attribute的用法
AttributeUsage 類是另一預(yù)定義類(譯者注:attribute類本身用這個atrribute System.AttributeUsage來標(biāo)記),它將幫助我們控制我們自定義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 值。(譯者注:默認(rèn)值為AttributeTargets.All)
AllowMultiple
該屬性標(biāo)識我們的自定義attribte能在同一語言元素上使用多次。(譯者注:該屬性為bool類型,默認(rèn)值為false,意思就是該自定義attribute在同一語言元素上只能使用一次)
Inherited
我們可以使用該屬性來控制我們的自定義attribute類的繼承規(guī)則。該屬性標(biāo)識我們的自定義attribute是否可以由派生類繼承。((譯者注:該屬性為bool類型,默認(rèn)值為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. 它規(guī)定這個help attribute 只能放置在語言元素”class”之上。這就意味著,下面的代碼將會產(chǎn)生一個錯誤。
AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.
現(xiàn)在試著把它綁定到方法。
[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 可以放置在任何預(yù)定義的語言元素上,那些可能的語言元素如下:
[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() { } }
它產(chǎn)生了一個編譯錯誤:
AnyClass.cs: Duplicate 'Help' attribute
Ok!現(xiàn)在我們該討論下***那個屬性了,”Inherited”, 指出當(dāng)把該attribute放置于一個基類之上,是否派生類也繼承了該attribute。如果綁定至某個attribute類的”Inherited”被設(shè)為true,那么該attribute就會被繼承,然而如果綁定至某個attribute類的”Inherited”被設(shè)為false或者沒有定義,那么該attribute就不會被繼承。
讓我們假設(shè)有如下的類關(guān)系。
[Help("BaseClass")] public class Base { } public class Derive : Base { }
我們有四種可能的綁定:
***種情況
如果我們查詢(我們將在后面來了解如何在運行時來查詢attributes)派生類中的help attribute,我們將不可能查詢到因為”Inherited”被設(shè)為了false。
第二種情況
第二種情況沒有什么不同,因為其”Inherited”也被設(shè)為了false。
第三種情況
為了解釋第三種和第四種情況,讓我們?yōu)榕缮愐步壎ㄍ籥ttribute。
[Help("BaseClass")] public class Base { } [Help("DeriveClass")] public class Derive : Base { }
現(xiàn)在我們查詢相關(guān)的help attribute ,我們將僅僅可以得到派生類的attribute,為什么這樣是因為help attribute雖然允許被繼承,但不能多次在同一語言元素上使用,所以基類中的help attribute被派生類的help attribute 重寫了。
第四種情況
在第四種情況中,當(dāng)我們查詢派生類的help attribute 時,我們可以得到兩個attributes,當(dāng)然是因為help attribute既允許被繼承,又允許在同一語言元素上多次使用的結(jié)果。
注意:AttributeUsage attribute 僅應(yīng)用在那種是System.Attribute 派生的attriubte類而且綁定值該attriubte類的AllowMultiple和Inherited均為false上才是有效的。
可選參數(shù) vs. 命名參數(shù)
可選參數(shù)是attribute類構(gòu)造函數(shù)的參數(shù)。它們是強(qiáng)制的,必須在每次在attribute綁定至某語言元素時提供一個值。而另一方面,命名參數(shù)倒是真正的可選參數(shù),不是在attribute構(gòu)造函數(shù)的參數(shù)。
為了更加詳細(xì)的解釋,讓我們在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 { }
當(dāng)我們在Class1中查詢Help attribute已經(jīng)它的屬性,我們將得到:
Help.Description : This is Class1
Help.Version :No Version is defined for this class
因為我們沒有為Version這個屬性定義任何任何值,所以在構(gòu)造函數(shù)中設(shè)定的值被我們查詢出來了。如果沒有定義任何值,那么就會賦一個該類型的默認(rèn)值(例如:如果是int型,默認(rèn)值就是0)。
現(xiàn)在,查詢Class2的結(jié)果是:
Help.Description : This is Class2
Help.Version : 1.0
我們不能為了可選參數(shù)而使用多個構(gòu)造函數(shù),應(yīng)該用已命名參數(shù)來代替。我們之所以稱它們?yōu)橐衙?,是因為?dāng)我們在構(gòu)造函數(shù)為它們提供值時,我們必須命名它們。例如,在第二個類中,我們?nèi)缡嵌xHelp。
[Help("This is Class2", Version = "1.0")]
在 AttributeUsage 例子中, 參數(shù)”ValidOn”是可選參數(shù),而“Inherited“和“AllowMultiple“ 是命名參數(shù)。
注意:為了在attribute的構(gòu)造函數(shù)中設(shè)定命名參數(shù)的值,我們必須為相應(yīng)的屬性提供一個set方法否則會引起編譯期錯誤:
'Version' : Named attribute argument can't be a read only property
現(xiàn)在,我們在Class3中查找Help attribute 及其屬性會發(fā)生什么呢?結(jié)果是跟上面提到的相同的編譯期錯誤。
'Desciption' : Named attribute argument can't be a read only property
現(xiàn)在我們修改下Help類,為屬性”Description”加一個set方法。現(xiàn)在的輸出就是:
Help.Description : This is do-nothing class
Help.Version : 2.0
在屏幕后面究竟發(fā)生了什么呢?首先帶有可選參數(shù)的構(gòu)造函數(shù)被調(diào)用,然后,每個命名參數(shù)的set方法被調(diào)用,在構(gòu)造函數(shù)中賦給命名參數(shù)的值被set方法所覆寫。
參數(shù)類型
一個attribute類的參數(shù)類型被限定在如下類型中:
Attributes 標(biāo)記
假設(shè),我們想把Help attribute 綁定至元素 assembly。***個問題是我們要把Help attribute 放在哪兒才能讓編譯器確定該attribute是綁定至整個assembly呢?考慮另一種情況,我們想把a(bǔ)ttribute綁定至一個方法的返回類型上,怎樣才能讓編譯器確定我們是把a(bǔ)ttribute綁定至方法的返回類型上,而不是整個方法呢?
為了解決諸如此類的含糊問題,我們使用attribute標(biāo)識符,有了它的幫助,我們就可以確切地申明我們把a(bǔ)ttribute 綁定至哪一個語言元素。
例如:
[assembly: Help("this a do-nothing assembly")]
這個在Help attribute 前的assembly標(biāo)識符確切地告訴編譯器,該attribute被綁定至整個assembly。可能的標(biāo)識符有:
在運行時查詢Attributes
現(xiàn)在我們明白怎么創(chuàng)建attribtes和把它們綁定至語言元素。是時候來學(xué)習(xí)類的使用者該如何在運行時查詢這信息。
為了查詢一語言元素上綁定的attributes,我們必須使用反射。反射有能力在運行時發(fā)現(xiàn)類型信息。
我們可以使用.NET Framework Reflection APIs 通過對整個assembly元數(shù)據(jù)的迭代,列舉出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() { } }
我們將在接下來的兩節(jié)中在我們的Main方法中加入attribute查詢代碼。
查詢程序集的Attributes
在接下來的代碼中,我們先得到當(dāng)前的進(jìn)程名稱,然后用Assembly類中的LoadForm()方法加載程序集,再有用GetCustomAttributes()方法得到被綁定至當(dāng)前程序集的自定義attributes,接下來用foreach語句遍歷所有attributes并試圖把每個attribute轉(zhuǎn)型為Help attribute(即將轉(zhuǎn)型的對象使用as關(guān)鍵字有一個優(yōu)點,就是當(dāng)轉(zhuǎn)型不合法時,我們將不需擔(dān)心會拋出異常,代之以空值(null)作為結(jié)果),接下來的一行就是檢查轉(zhuǎn)型是否有效,及是不是為空,跟著就顯示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類相關(guān)聯(lián)的Type型對象。剩下的查詢類attributes代碼就與上面的例子是相似的,應(yīng)該不要解釋了吧(我是這么想的)。
為查詢方法和類成員的attributes,首先我們得到所有在類中存在的方法和成員,然后我們查詢與它們相關(guān)的所有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”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
網(wǎng)頁標(biāo)題:C#中如何使用Attributes
分享路徑:http://bm7419.com/article42/pcgjec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計、網(wǎng)站改版、網(wǎng)站收錄、手機(jī)網(wǎng)站建設(shè)、網(wǎng)站策劃、品牌網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)