欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Attributes in c#
原文出處Attributes in C#,CodeProject
摘要
在這篇指南里,我們將會(huì )看到如何自己創(chuàng )建屬性(Attribute),并將其用到不同的程序實(shí)體(Entity)上,在程序運行時(shí)獲取屬性信息。
譯注
MSDN將 Attribute 與 Property 均譯作“屬性”。我真不知道該怎么譯了,就將 Property 譯作“數據屬性”吧。
介紹
屬性(Attribute)是一種新型的聲明信息。我們可以使用屬性來(lái)定義設計時(shí)的信息(比如幫助文件、文檔的鏈接),以及運行時(shí)的信息(比如將一個(gè)類(lèi)的域與一個(gè)XML的域相關(guān)聯(lián))。我們也可以用屬性來(lái)創(chuàng )建“自描述”的組件(可以提供該組件的描述信息)。在這篇指南里,我們將會(huì )看到如何自己創(chuàng )建屬性(Attribute),并將其用到不同的程序實(shí)體(Entity)上,并在程序運行時(shí)獲取屬性信息。
屬性的概念
MSDN(ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsharpspec_17_2.htm)里是這樣定義的:屬性是一個(gè)聲明的附加聲明。
使用預定義的屬性
C#已經(jīng)預定義了一小組的屬性供我們使用。在學(xué)習如何創(chuàng )建一個(gè)自定義的屬性前,我們先通過(guò)一段代碼來(lái)看看怎么使用這些預定義的屬性吧。
using System;public class AnyClass{[Obsolete("別用Old這個(gè)老方法了,請用New方法", true)]static void Old( ) { }static void New( ) { }public static void Main( ){Old( );}}   在這個(gè)例子里我們使用了Obsolete(“陳舊的”)屬性,它會(huì )將其所修飾的程序實(shí)體(類(lèi)、方法、數據成員等)說(shuō)明為已廢棄不用的。第一個(gè)參數—一個(gè)字符串說(shuō)明這個(gè)實(shí)體為何被廢棄、由誰(shuí)代替。實(shí)際上這個(gè)字符串的內容你想寫(xiě)什么都可以。第二個(gè)參數則告訴編譯器將用戶(hù)對此實(shí)體的調用視作一個(gè)編譯錯誤。這個(gè)參數的缺省值為false,表示編譯器僅將用戶(hù)對其的調用視作警告。編譯上面這段代碼時(shí),我們將會(huì )得到一個(gè)編譯錯誤(譯注:注意編譯錯誤后附的提示了嗎?):AnyClass.Old() is obsolete:“別用Old這個(gè)老方法了,請用New方法”
開(kāi)發(fā)自定義的屬性
現在開(kāi)始開(kāi)發(fā)我們自己的屬性吧。這兒有一個(gè)小竅門(mén):從C#定義的System.Attribute類(lèi)派生我們的屬性類(lèi)(從抽象基類(lèi)System.Attribute直接或間接地派生一個(gè)類(lèi),該派生類(lèi)都是一個(gè)屬性類(lèi)。一個(gè)屬性類(lèi)的聲明就定義了一種新的屬性類(lèi)型),然后得到了這樣一個(gè)聲明:using System;public class HelpAttribute : Attribute{}不管你相不相信,我們已經(jīng)創(chuàng )建了一個(gè)自定義的屬性。我們可以象這樣用它修飾任何的類(lèi):[Help()]public class AnyClass{}注意:
在屬性類(lèi)名與后綴Attribute間存在一個(gè)自動(dòng)的編譯轉換。因此當我們用一個(gè)屬性去修飾一個(gè)程序實(shí)體時(shí),不需要給出Attribute這個(gè)后綴。編譯器首先會(huì )在System.Attribute的所有派生類(lèi)中進(jìn)行匹配,如果沒(méi)有找到匹配屬性,它就將屬性名加上Attribute后綴名后再進(jìn)行匹配。
目前我們的這個(gè)屬性還沒(méi)什么用,讓我們加點(diǎn)內容吧。在這個(gè)示例里,我們?yōu)樽远x的屬性類(lèi)添加了一個(gè)數據屬性Description(Property),我們將在本文的最后演示如何在運行時(shí)查詢(xún)這些信息。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("這是個(gè)什么也不做的類(lèi)")]public class AnyClass{}
定義/控制自定義屬性的使用
AttributeUsage 類(lèi)是另一個(gè)預定義的屬性類(lèi),以幫助我們控制自定義屬性的使用。亦即我們可以定義自定義屬性類(lèi)的屬性。這個(gè)類(lèi)描述了如何使用自定義的屬性類(lèi)。AttributeUsage有三個(gè)數據屬性可用以修飾我們的自定義的屬性:
ValidOn
定義了自定義屬性在哪些程序實(shí)體上可被使用。這個(gè)可使用實(shí)體的列表可通過(guò)AttributeTargets枚舉類(lèi)型的OR操作進(jìn)行設置
AllowMultiple 定義了是否可在同一個(gè)程序實(shí)體上同時(shí)使用多個(gè)屬性進(jìn)行修飾
Inherited 定義了自定義屬性的修飾是否可由被修飾類(lèi)的派生類(lèi)繼承
讓我們做點(diǎn)具體的吧。我們將會(huì )用一個(gè)AttributeUsage屬性修飾我們的屬性類(lèi),以控制其作用范圍:
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,說(shuō)明了我們的Help屬性只能用以修飾類(lèi),下面的這段代碼將會(huì )導致一個(gè)編譯錯誤(“屬性Help不能用在這樣的聲明上,它只能用在類(lèi)的聲明上”),因為我們用Help屬性去修飾方法AnyMethod()了:
[Help("this is a do-nothing class")]public class AnyClass{[Help("this is a do-nothing method")] //errorpublic void AnyMethod(){}}編譯錯誤:AnyClass.cs: Attribute ''Help'' is not valid on this declaration type.It is valid on ''class'' declarations only.  當然我們可以AttributeTargets.All來(lái)允許Help屬性修飾任何類(lèi)型的程序實(shí)體。AttributeTargets可能的值包括: 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 )
接下來(lái),該看看AllowMultiple = false這句了:它確定了不能象下面這樣,在同一實(shí)體上同時(shí)使用多個(gè)同種屬性進(jìn)行修飾:[Help("this is a do-nothing class")][Help("it contains a do-nothing method")]public class AnyClass{[Help("this is a do-nothing method")] //這也是錯誤的,因為Help屬性只能修飾類(lèi)public void AnyMethod(){}}編譯錯誤: AnyClass.cs: Duplicate ''Help'' attribute  我們再來(lái)談?wù)凙ttributeUsage的最后一個(gè)數據屬性Inherited:定義了自定義屬性的修飾是否可由被修飾類(lèi)的派生類(lèi)繼承?;谙率敬a表示的繼承關(guān)系,讓我們看看會(huì )發(fā)生什么吧:[Help("BaseClass")]public class Base{}public class Derive : Base{}我們選擇了AttributeUsage的四種組合: [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 ]
對應上述組合的結果: 如果我們查詢(xún)(稍后我們會(huì )看見(jiàn)如何在運行時(shí)查詢(xún)一個(gè)類(lèi)的屬性信息。)這個(gè)Derive類(lèi)的Help屬性時(shí),會(huì )因其未從基類(lèi)繼承該屬性而一無(wú)所獲。 因為同樣的原因,得到與結果一同樣的結果。 為了解釋這后面的兩種情況,我們把同樣的屬性也用在這個(gè)Derive派生類(lèi)上,代碼修改如下: [Help("BaseClass")] public class Base { } [Help("DeriveClass")] public class Derive : Base { } 我們的查詢(xún)會(huì )同時(shí)得到其類(lèi)Base與派生類(lèi)Dervie的Help屬性信息,因為繼承與多重修飾均被允許。
注意:
AttributeUsage只能用于System.Attribute的派生類(lèi),且該派生類(lèi)的AllowMultiple與Inherited都為false。
定位參數與命名參數
定位參數是屬性類(lèi)構造子(Constructor)的參數。它們是每次使用該屬性修飾某個(gè)程序實(shí)體時(shí)都必須提供值的參數。相對的,命名參數則是可選參數,它也不是屬性類(lèi)構造子的參數。為了詳細解釋它們的含義,讓我們給Help屬性類(lèi)加點(diǎn)內容,然后看看下面的示例:[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;}//即便我們不想我們的屬性用戶(hù)設置Version這個(gè)數據屬性,我們也不得不提供set方法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{}我們查詢(xún)Class1的Help屬性信息時(shí),會(huì )得到下列結果:Help.Description : This is Class1Help.Version :No Version is defined for this class  如果我們不定義Version數據屬性的值,那么構造子函數體內所賦的缺省值將會(huì )使用。如果也沒(méi)有,那么該數據屬性對應的數據類(lèi)型的缺省值將被使用(比如int類(lèi)型的缺省值為0)。查詢(xún)Class2將會(huì )得到這樣的結果:Help.Description : This is Class2Help.Version : 1.0  請不要為了可選的參數而提供多個(gè)構造子的重載版本,而應該將它們定義成命名參數。我們之所以稱(chēng)其為“命名的”,是我們?yōu)榱四茉跇嬙熳永锝o它們賦值,不得不用一個(gè)個(gè)的標識符定義和訪(fǎng)問(wèn)它們。比如在第二個(gè)類(lèi)中Help屬性的使用[Help("This is Class2", Version = "1.0")] 你瞧,AttributeUsage的ValidOn參數就是一個(gè)定位參數,而Inherited與AllowMultiple則是命名參數?! ∽⒁猓涸趯傩灶?lèi)的構造子中給命名參數賦值,我們必須為它提供一個(gè)相應的set方法,否則會(huì )導致這樣的編譯錯誤(Version不能是一個(gè)只讀的數據屬性):''Version'' : Named attribute argument can''t be a read only property  當我們查詢(xún)Class3的Help屬性信息時(shí)會(huì )發(fā)生什么呢?會(huì )這樣-因上述的原因導致編譯錯誤(Description不能是只讀的數據屬性):''Desciption'' : Named attribute argument can''t be a read only property所以還是給Description添加一個(gè)set方法吧。這樣會(huì )得到正確的輸出結果:This is do-nothing classHelp.Version : 2.0  這是因為構造子利用定位參數構造一個(gè)屬性時(shí),它會(huì )調用所有命名參數的set方法。構造子里的賦值行為實(shí)際均由各命名參數對應的數據屬性的set方法完成,被其覆寫(xiě)(Override)了。
參數類(lèi)型
一個(gè)屬性類(lèi)的參數可使用的數據類(lèi)型限于: bool byte char double float int long short string System.Type object 枚舉類(lèi)型以及上述數據類(lèi)型的一維數組
屬性標識
讓我們想象一下,怎么才能把我們的Help屬性用到一個(gè)完整的程序集(assembly)上?首先要面對的問(wèn)題是該把Help屬性放在哪兒,以便讓編譯器識別出它是屬于一個(gè)程序集的?再考慮另一種情況:我們想把一個(gè)屬性用在某個(gè)方法的返回類(lèi)型上時(shí),編譯器如何才能確定我們把它用在了返回類(lèi)型而不是這個(gè)方法本身之上?要解決這么多含糊的問(wèn)題,我們需要屬性標識。借助屬性標識的幫助,我們可以明確地告訴程序集我們希望把屬性放在哪兒。比如:[assembly: Help("this a do-nothing assembly")]  這個(gè)Help屬性前的assembly標識符顯式地告訴了編譯器,當前這個(gè)Help屬性用于整個(gè)程序集??捎玫臉俗R符包括: assembly module type method property event field param return
在運行時(shí)查詢(xún)屬性
我們已經(jīng)知道了如何創(chuàng )建屬性并如何在程序中使用它們?,F在該學(xué)習我們所建屬性類(lèi)的用戶(hù)如何才能在運行時(shí)查詢(xún)該屬性類(lèi)的信息了。要查詢(xún)一個(gè)程序實(shí)體的所有屬性信息,我們得使用反射(reflection)-在運行時(shí)發(fā)現類(lèi)型信息的一種功能。
我們可以直接使用.NET Framework提供的反射Reflection API來(lái)枚舉一個(gè)完整程序集的所有元數據(metadata),并產(chǎn)生該程序集所有類(lèi)、類(lèi)型、方法的列表。還記得之前的Help屬性和AnyClass類(lèi)嗎?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 classpublic class HelpAttribute : Attribute{public HelpAttribute(String Description_in){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(){}}  我們將在接下來(lái)的兩節里在我們的Main方法里加入屬性查詢(xún)的代碼。
查詢(xún)程序集的屬性
在接下來(lái)的代碼片段里,我們獲取當前進(jìn)程的名字,并使用Assembly類(lèi)的LoadFrom方法裝載程序集。然后我們使用GetCustomAttributes方法獲取當前程序集的所有自定義屬性。接下來(lái)的foreach語(yǔ)句又遍歷所有的屬性對象,并試著(zhù)將這些屬性轉化為Help屬性(使用as關(guān)鍵字進(jìn)行轉換,如果轉換失敗,將會(huì )返回一個(gè)空值而不是觸發(fā)一個(gè)異常)。再后的一條語(yǔ)句是指如果轉換成功,則顯示Help屬性的所有數據屬性信息。class QueryApp{public static void Main(){HelpAttribute HelpAttr;//Querying Assembly AttributesString 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 andtheir run-time query.Press any key to continue
查詢(xún)類(lèi)、方法和域的屬性
在下面的代碼片段里,和上面的代碼不同的只是Main方法的第一條語(yǔ)句變成了:Type type = typeof(AnyClass);  它使用typeof操作符返回AnyClass對應的Type對象。其余的代碼也類(lèi)似上述的代碼,我想不需要再做解釋了吧。要查詢(xún)方法和域的屬性,我們首先要獲得當前類(lèi)中所有方法和類(lèi),然后再用類(lèi)似于查詢(xún)類(lèi)的屬性的方法來(lái)查詢(xún)與之對應的屬性。class QueryApp{public static void Main(){Type type = typeof(AnyClass);HelpAttribute HelpAttr;//Querying Class Attributesforeach (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 Attributesforeach(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) Attributesforeach(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);}}}}}下面是程序輸出:Description of AnyClass:This is a do-nothing Class.Description of AnyMethod:This is a do-nothing Method.Description of AnyInt:This is any Integer.Press any key to continue
關(guān)于作者
Sadaf Alvi,卡拉奇大學(xué)的自然科學(xué)學(xué)士,主頁(yè)http://www24.brinkster.com/salvee
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C# 特性詳解
C#反射機制
OpenLDAP的Schema擴展
C#中的特性(Attributes)(翻譯)
Unity 屬性繪制器
常用Design屬性
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久