日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

[C#]Attribute特性(2)——方法的特性及特性参数

發(fā)布時(shí)間:2023/12/31 C# 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [C#]Attribute特性(2)——方法的特性及特性参数 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?上篇博文[C#]Attribute特性介紹了特性的定義,類的特性,字段的特性,這篇博文將介紹方法的特性及特性參數(shù)相關(guān)概念。

3.方法的特性?

????? 之所以將這部分單列出來(lái)進(jìn)行討論,是因?yàn)閷?duì)方法的特性查詢的反射代碼不同于對(duì)類的特性查詢的反射代碼。在這個(gè)例子里,我們將使用一個(gè)特性用來(lái)定義一種可進(jìn)行事務(wù)處理的方法。???

1 public class TransactionableAttribute : Attribute 2 { 3 public TransactionableAttribute() { } 4 } 1 public class TestClass 2 { 3 [Transactionable] 4 public void Foo() 5 { } 6 public void Bar() 7 { } 8 [Transactionable] 9 public void Baz() 10 { } 11 } 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Type type = typeof(TestClass); 6 foreach (MethodInfo method in type.GetMethods()) 7 { 8 foreach (Attribute attr in method.GetCustomAttributes()) 9 { 10 if (attr is TransactionableAttribute) 11 { 12 Console.WriteLine("{0} is transactionable.", method.Name); 13 } 14 } 15 } 16 Console.Read(); 17 } 18 }

??? 代碼輸出結(jié)果為:

????

????? 在這個(gè)特殊的例子,僅僅憑借TransactionableAttribute就可以讓代碼知道具有這種特性的方法可以參與事務(wù)處理。這也是為什么在這里只有一個(gè)簡(jiǎn)單的、不帶參數(shù)的構(gòu)造函數(shù),而沒有其他成員。然后TestClass定義三種方法:Foo方法、Bar方法和Baz方法;其中Foo方法和Baz方法方法被定義為具有處理事務(wù)能力的方法。請(qǐng)注意您附加一個(gè)帶構(gòu)造函數(shù)的特性時(shí),如果這個(gè)構(gòu)造函數(shù)不帶參數(shù),您就不需要把左括號(hào)和右括號(hào)包括進(jìn)去了。

???? ?現(xiàn)在讓我們看看這個(gè)程序當(dāng)中指的關(guān)注的部分,看看怎樣通過(guò)方法的特性來(lái)查詢類的方法。我們開始先用typeof來(lái)獲得TestClass類的System.Type對(duì)象。

1 Type type = typeof(TestClass);

?????? 然后我們使用Type.GetMethods方法來(lái)得到一個(gè)MethodInfo對(duì)象數(shù)組。每一個(gè)這樣的對(duì)象包括TestClass類的一個(gè)方法信息。我們用foreach語(yǔ)句來(lái)循環(huán)處理我們的每一個(gè)方法。

1 foreach (MethodInfo method in type.GetMethods())

??? 現(xiàn)在我們有一個(gè)MethodInfo對(duì)象,我們就可以使用MethodInfo.GetCustomAttributes()方法來(lái)得到所有的用戶創(chuàng)建的方法特性。我們還是使用foreach語(yǔ)句來(lái)循環(huán)處理返回的對(duì)象數(shù)組。

1 foreach (Attribute attr in method.GetCustomAttributes())

???????在代碼的這個(gè)地方,我們的方法有了特性?,F(xiàn)在,通過(guò)使用is操作符,我們來(lái)判斷一個(gè)特性是不是一個(gè)TransactionableAttribute,如果他是,就打印出這個(gè)方法的名字。

1 if (attr is TransactionableAttribute) 2 { 3 Console.WriteLine("{0} is transactionable.", method.Name); 4 }

特性的參數(shù)

????? 在上面的例子中,通過(guò)構(gòu)造函數(shù)我們討論了附加特性的使用?,F(xiàn)在我們要來(lái)看看在前面沒有談到的特性的構(gòu)造函數(shù)的一些方面。

定位參數(shù)和命名參數(shù)

????? 在上一篇博文字段的特性的例子中,您看到一個(gè)名為RefistryKeyAttribute的特性。它的構(gòu)造函數(shù)形式如下:

1 public RegistryKeyAttribute(RegistryHives Hive, string valueName)

????? 在這個(gè)構(gòu)造函數(shù)聲明之后,通過(guò)如下這種形式特性就附加給了一個(gè)字段:

1 [RegistryKey(RegistryHives. HKEY_CURRENT_USER,"Foo")] 2 public string Foo;

?????? 到此為止,這些都很容易理解。這個(gè)構(gòu)造函數(shù)有兩個(gè)參數(shù),這兩個(gè)參數(shù)都是在把一個(gè)特性附加給一個(gè)字段時(shí)用到的。不過(guò),我們可以讓這種編程更簡(jiǎn)單。如果這個(gè)參數(shù)大多數(shù)時(shí)候都不變,那為什么每次都要讓使用這個(gè)類的用戶再費(fèi)勁地輸入這些參數(shù)呢?我們可以使用定位參數(shù)(position parameter)和命名參數(shù)來(lái)給這些參數(shù)設(shè)置默認(rèn)值。

???? 定位參數(shù)是用在構(gòu)造函數(shù)中的參數(shù)。在每次使用特性時(shí)它們是必須的參數(shù),并且要必須指明這些參數(shù)。在上面的RegistryKeyAttribute例子中,Hive和ValueName都是定位參數(shù)。命名參數(shù)在特性的構(gòu)造函數(shù)中實(shí)際上并沒有定義,更確切地說(shuō),它們是非靜態(tài)的字段和屬性。因此,在一個(gè)特性被實(shí)例化時(shí),命名參數(shù)讓客戶端能夠設(shè)置這個(gè)特性的字段和屬性,而不必讓您為客戶端要設(shè)置的每一種字段和屬性的可能的組合而創(chuàng)建構(gòu)造函數(shù)。

???? 每一個(gè)公共的構(gòu)造函數(shù)都可以定義一系列的定位參數(shù),就像所有類型的類一樣。但是,對(duì)于特性來(lái)說(shuō),一旦它的定位參數(shù)被確定,用戶就可以使用FieldOrPropertyName=Value來(lái)對(duì)某個(gè)字段或?qū)傩赃M(jìn)行引用。下面我們通過(guò)對(duì)特性RegistryKeyAttribute的修改來(lái)解釋一下這種情況。在這個(gè)例子里,我們?nèi)egistryKeyAttribute.ValueName作為一個(gè)定位參數(shù),而RegistryKeyAttribute.Hive就成了可選的命名參數(shù)。接下來(lái),問題就是“您怎樣才能把一些參數(shù)定義為命名參數(shù)?”因?yàn)橹挥卸ㄎ粎?shù)——即必需性的——參數(shù)才包括在構(gòu)造函數(shù)的定義中,因此我們只需簡(jiǎn)單地把這個(gè)可選參數(shù)從構(gòu)造函數(shù)的定義中刪除即可。然后用戶就可以引用如下部分作為命名參數(shù):非只讀、靜態(tài)或常量的任何字段,或包括設(shè)置存取器方法或非靜態(tài)的setter的任何屬性。因此,為了使RegistryKeyAttribute.Hive成為一個(gè)命名參數(shù),我們要把它從構(gòu)造函數(shù)的定義中刪除,因?yàn)樗鳛橐粋€(gè)公共的讀/寫屬性已經(jīng)存在了。

public RegistryKeyAttribute(string valueName)

???? 用戶現(xiàn)在就可以用下面的任一種方法來(lái)附加特性了:

1 [RegistryKey(“Foo”)] 2 [RegistryKey(“Foo”,Hive=RegistryHives.HKEY_LOCAL_MACHINE)]

????? 采用這種方式具有很好的靈活性,您既可以使用字段的默認(rèn)值,同時(shí),又可以讓用戶能夠在需要的時(shí)候用其他值覆蓋原來(lái)的默認(rèn)值。但是要記住:如果用戶沒有設(shè)置RegistryKeyAttribute.Hive字段的值,我們?cè)鯓觼?lái)默認(rèn)它?您也許會(huì)想到,“哦,我們來(lái)檢查一下看它是不是在構(gòu)造函數(shù)中設(shè)置了?!钡?#xff0c;問題是RegistryKeyAttribute.Hive是一個(gè)enum型的,它的底層數(shù)據(jù)類型是int型——它是一個(gè)數(shù)值。這就意味著在定義時(shí)編譯器已經(jīng)把它初始化為0了!如果我們測(cè)試一下構(gòu)造函數(shù)中RegistryKeyAttribute.Hive的值就會(huì)發(fā)現(xiàn)它等于0,我們不知道,是由調(diào)用程序通過(guò)命名參數(shù)設(shè)置的那個(gè)值,還是由編譯器在編譯時(shí),因?yàn)樗且粋€(gè)數(shù)值型才給它設(shè)置了該值。不幸的是,現(xiàn)在能解決這個(gè)問題的唯一的途徑是改變這段代碼,讓它的值為0時(shí)無(wú)效。這可以通過(guò)如下改變RegistryHives enum的方式實(shí)現(xiàn):?

1 public enum RegistryHives 2 { 3 HKEY_CLASSES_ROOT=1, 4 HKEY_CURRENT_USER, 5 HKEY_LOCAL_MACHINE, 6 HKEY_USERS, 7 HKEY_CURRENT_CONFIG 8 }

????? 現(xiàn)在我們知道,使RegistryKeyAttribute.Hive為0的唯一途徑是編譯器把它初始化為0,并且用戶沒有通過(guò)一個(gè)命名參數(shù)來(lái)覆蓋它的初值。我們可以用類似下面的代碼來(lái)將其初始化:

1 public RegistryKeyAttribute(string valueName) 2 { 3 this.valueName = valueName; 4 if (this.Hive == 0) 5 { 6 this.hive = RegistryHives.HKEY_CURRENT_USER; 7 } 8 }

使用命名參數(shù)時(shí)的常見錯(cuò)誤

??????當(dāng)您使用命名參數(shù)時(shí),您必須首先要指定定位參數(shù)。之后,由于命名參數(shù)是放在字段名或?qū)傩灾暗?#xff0c;因此命名參數(shù)之間沒有先后順序。下面的例子將導(dǎo)致一個(gè)編譯錯(cuò)誤。

1 //This is an error because postional parameters can't follow 2 //named parameters 3 [RegistryKey(Hive=RegistryHives.HKEY_LOCAL_MACHINE, "Foo")]

????? 另外,您不能命名定位參數(shù)。編譯器在編譯特性的使用時(shí),它會(huì)試著先去解析那些命名參數(shù)。然后再試著根據(jù)方法特性去解析剩下的——定位參數(shù)值。本段下面的代碼無(wú)法通過(guò)編譯,因?yàn)樵谝馕龅膮?shù)當(dāng)中必須半酣至少一個(gè)定位參數(shù),如果全部都是命名參數(shù),就會(huì)出現(xiàn)提示“No overload for method 'Registrykey Attribute 'takes ' O' arguments”(RegistrykeyAttribute方法沒有參數(shù)值,無(wú)法進(jìn)行重載)。

1 [RegistryKey(ValueName="Foo",Hive=RegistryHives.HKEY_LOCAL_MACHINE)]

???? 最后,命名參數(shù)可以是任何公共的、可存取的字段或?qū)傩浴╯etter方法——只要不是靜態(tài)的或常量即可。

有效的特性參數(shù)類型

????? 特性類的定位參數(shù)和命名參數(shù)的類型僅限于特性參數(shù)類型,這些包括:

  • bool,byte,char,double,float,int,long,short,string
  • System.Type
  • object
  • enum類型,前提是它或任何有它嵌套在里面的類型必須是公共的可存取類型——就像在那個(gè)使用RegistryHives枚舉的例子中一樣。
  • 由上述的任何類型組成的一維數(shù)組。

???? 因?yàn)橛行У膮?shù)類型僅局限于上述列出來(lái)的類型,因此您不能把一個(gè)像類那樣的數(shù)據(jù)結(jié)構(gòu)傳遞給特性構(gòu)造函數(shù)作為參數(shù)。這種限制很有意義,因?yàn)樘匦允窃诔绦蛟O(shè)計(jì)時(shí)附加上的,此時(shí)您并沒有這個(gè)類(對(duì)象)的實(shí)例化的實(shí)例。使用上面列出來(lái)的這些有效類型,您就可以在程序設(shè)計(jì)時(shí)把他們的值固定下來(lái),就是為什么能使用他們的原因。

結(jié)語(yǔ)

???? 方法的特性和特性參數(shù)就介紹到這里,您如果想了解更多請(qǐng)參考《c#技術(shù)內(nèi)幕》這本書,本文也是摘自這本書,記錄在此,方便回顧,也分享給大家,希望能對(duì)您有所幫助。下篇將學(xué)習(xí)AttributeUsage特性和特性標(biāo)識(shí)符。敬請(qǐng)期待......

?

?

?

博客地址:http://www.cnblogs.com/wolf-sun/
博客版權(quán):本文以學(xué)習(xí)、研究和分享為主,歡迎轉(zhuǎn)載,但必須在文章頁(yè)面明顯位置給出原文連接。
如果文中有不妥或者錯(cuò)誤的地方還望高手的你指出,以免誤人子弟。如果覺得本文對(duì)你有所幫助不如【推薦】一下!如果你有更好的建議,不如留言一起討論,共同進(jìn)步!
再次感謝您耐心的讀完本篇文章。

轉(zhuǎn)載:http://www.cnblogs.com/wolf-sun/p/3392765.html

總結(jié)

以上是生活随笔為你收集整理的[C#]Attribute特性(2)——方法的特性及特性参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。