在.NET運行時瞭解類型信息(3)

訪問自定義屬性<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

當屬性與程序元素相關聯後,可以使用反射來查詢它們是否存在以及它們的值。用於查詢屬性的主要反射方法包含在 System.Reflection.MemberInfo.GetCustomAttributes 和 System.Reflection.Assembly.GetCustomAttributes 中。

自定義屬性的可訪問性根據附加該屬性的程序集來進行檢查。這相當於檢查附加自定義屬性的程序集中的類型上的方法是否可以調用自定義屬性的構造函數。

諸如 System.Reflection.Assembly.GetCustomAttributes(Type, Boolean) 等方法檢查類型參數的可見性和可訪問性。只有包含用戶定義類型的程序集中的代碼才能使用 GetCustomAttributes 檢索該類型的自定義屬性。

以下代碼示例是典型的自定義屬性設計模式。它說明運行庫自定義屬性反射模型。

[C#]

System.DLL

public class DescriptionAttribute : Attribute

{

}

 

   System.Web.DLL

   internal class MyDescriptionAttribute : DescriptionAttribute

   {

   }

 

   public class LocalizationExtenderProvider

   {

      [MyDescriptionAttribute(...)]

      public CultureInfo GetLanguage(...)

   {

   }

}

如果試圖爲附加到 GetLanguage 方法的公共自定義屬性類型 DescriptionAttribute 檢索自定義屬性,運行庫將執行以下操作:

  1. 運行庫檢查 Type.GetCustomAttributes(Type type) 的 DescriptionAttribute 類型參數是否爲公共的,並檢查其是否可見或可以訪問。

  2. 運行庫檢查從 DescriptionAttribute 導出的用戶定義類型 MyDescriptionAttribute System.Web.DLL 程序集(它在該程序集中附加到 GetLanguage() 方法)內是否可見和可以訪問。

  3. 運行庫檢查 MyDescriptionAttribute 的構造函數是否在 System.Web.DLL 程序集中可見和可以訪問。

  4. 運行庫調用帶有自定義屬性參數的 MyDescriptionAttribute 的構造函數,然後將新對象返回給調用方。

自定義屬性反射模型可能會在定義類型的程序集外泄漏用戶定義類型的實例。這與運行庫系統庫中返回用戶定義類型的實例的成員(例如返回 RuntimeMethodInfo 對象數組的 Type.GetMethods())相同。爲了防止客戶端發現關於用戶定義的自定義屬性類型的信息,請將該類型的成員定義爲非公共成員。

以下代碼示例說明使用反射訪問自定義屬性的基本方法。

 [C#]

class MainClass

{

public static void Main()

{

   System.Reflection.MemberInfo info = typeof(MyClass);

   object[] attributes = info.GetCustomAttributes();

   for (int i = 0; i < attributes.Length; i ++)

      {

      System.Console.WriteLine(attributes[i]);

      }

   }

}

指定完全限定的類型名稱

要爲各種反射操作提供有效的輸入,必須指定類型名稱。完全限定的類型名稱包含程序集名稱指定、命名空間指定和類型名稱。類型名稱指定將由 Type.GetType、Module.GetType、ModuleBuilder.GetType 和 Assembly.GetType 來使用。

類型名稱的 Backus-Naur 形式語法

Backus-Naur 形式 (BNF) 定義正式語言的語法。下表中的 BNF 詞法規則將說明如何識別有效的輸入。最終元素(無法再減小的元素)將全部以大寫字母顯示。非最終元素(可以再減小的元素)則顯示爲大小寫混合或帶單引號的字符串,但單引號 (') 不是語法本身的一部分。管道字符 (|) 表示具有子規則的規則。

完全限定類型名稱的 BNF 語法

TypeSpec                          :=   ReferenceTypeSpec

                                  |    SimpleTypeSpec

ReferenceTypeSpec                 :=   SimpleTypeSpec '&'

SimpleTypeSpec                    :=   PointerTypeSpec

                                  |    ArrayTypeSpec

                                  |    TypeName

PointerTypeSpec                   :=   SimpleTypeSpec '*'

ArrayTypeSpec                     :=   SimpleTypeSpec '[ReflectionDimension]'

                                  |    SimpleTypeSpec '[ReflectionEmitDimension]'

ReflectionDimension               :=   '*'

                                  |    ReflectionDimension ',' ReflectionDimension

                                  |    NOTOKEN

ReflectionEmitDimension           :=   '*'

                                  |    Number '..' Number

                                  |    Number '...'

                                  |    ReflectionDimension ',' ReflectionDimension

                                  |    NOTOKEN

Number                            :=   [0-9]+

TypeName                          :=   NamespaceTypeName

                                  |    NamespaceTypeName ',' AssemblyNameSpec

NamespaceTypeName                 :=   NestedTypeName

                                  |    NamespaceSpec '.'NestedTypeName

NestedTypeName                    :=   IDENTIFIER

                                  |    NestedTypeName '+' IDENTIFIER

NamespaceSpec                     :=   IDENTIFIER

                                  |    NamespaceSpec '.'IDENTIFIER

AssemblyNameSpec                  :=   IDENTIFIER

                                  |    IDENTIFIER ',' AssemblyProperties

AssemblyProperties                :=   AssemblyProperty

                                  |    AssemblyProperties ',' AssemblyProperty

AssemblyProperty                  :=   AssemblyPropertyName '=' AssemblyPropertyValue

指定特殊字符

TypeName 中,IDENTIFIER 是由語言規則所確定的任何有效名稱。

反斜槓 (/) 可用作轉義符來分隔以下用作 IDENTIFIER 一部分的標記。

標記

含義

/,

程序集分隔符。

/+

嵌套類型分隔符。

/&

引用類型。

/*

指針類型。

/[

數組維度分隔符。

/]

數組維度分隔符。

/.

只有在數組指定中使用句點時,才應在句點前使用反斜槓。NamespaceSpec 中的句點不採用反斜槓。

//

用作字符串的反斜槓。

請注意,在除 AssemblyNameSpec 之外的所有 TypeSpec 組成部分中,空格都是相關的。在 AssemblyNameSpec 中,“,”分隔符之前的空格相關,但“,”分隔符之後的空格將被忽略。

反射類(如 Type.FullName)將返回經過處理的名稱,以便使返回的名稱可以在對 GetType 的調用中使用(例如在 MyType.GetType(myType.FullName) 中)。

例如,某個類型的完全限定名稱可能是 Ozzy.OutBack.Kangaroo+Wallaby,MyAssembly

如果命名空間爲 Ozzy.Out+Back,則必須在加號前加反斜槓。否則,分析器會將其解釋爲嵌套分隔符。反射會將該字符串當作 Ozzy.Out/+Back.Kangaroo+Wallaby,MyAssembly 發出。

指定程序集名稱

程序集名稱指定中所需的最少信息爲程序集的文本名稱 (IDENTIFIER)。您可以在 IDENTIFIER 後添加下表所述的逗號分隔屬性/值對列表。IDENTIFIER 命名應遵循文件命名的規則。IDENTIFIER 不區分大小寫。

有效的程序集屬性

屬性名稱

說明

允許值

Version

程序集版本號

Major.Minor.Build.Revision,其中 MajorMinorBuildRevision 是 0 和 65535 之間(含 0 和 65535)的整數。

PublicKey

完全公鑰

完全公鑰的十六進制字符串值。指定 null(在 Microsoft Visual Basic .NET 中爲 Nothing)可顯式地指示私有程序集。

PublicKeyToken

公鑰標記(完全公鑰的 8 字節哈希)

公鑰標記的十六進制字符串值。指定 null(在 Visual Basic .NET 中爲 Nothing)可顯式地指示私有程序集。

Culture

程序集區域性

程序集的 RFC-1766 格式區域性,或者對於獨立於語言(非附屬)的程序集爲“非特定”。

Custom

自定義的二進制大對象 (BLOB)。它當前僅用於由本機圖像生成器 (Ngen.exe) 生成的程序集。

自定義的字符串,由本機圖像生成器工具用來向程序集緩存通知所安裝的程序集爲本機圖像,因此將安裝在本機圖像緩存中。也稱作 Zap 字符串。

以下代碼示例顯示帶有默認區域性且名稱簡單的程序集的 AssemblyName

以下代碼示例顯示區域性爲“en”且帶有強名稱的程序集的完全限定引用。

以下代碼示例顯示部分指定的 AssemblyName,它可以由帶有強名稱或簡單名稱的程序集來滿足。

以下每個代碼示例都顯示一個部分指定的 AssemblyName,它必須由帶有簡單名稱的程序集來滿足。

以下每個代碼示例都顯示一個部分指定的 AssemblyName,它必須由帶有強名稱的程序集來滿足。

指定指針

SimpleTypeSpec* 表示非託管指針。例如,要獲取指向 MyType 類型的指針,請使用 Type.GetType("MyType*")。要獲取指向 MyType 類型指針的指針,請使用 Type.GetType("MyType**")

指定引用

SimpleTypeSpec & 表示託管指針或引用。例如,要獲取對 MyType 類型的引用,請使用 Type.GetType("MyType &")。請注意,與指針不同,引用僅限於一個級別。

指定數組

BNF 語法中,ReflectionEmitDimension 僅適用於使用 ModuleBuilder.GetType 檢索的不完整類型定義。不完整的類型定義是使用 Reflection.Emit 構造的 TypeBuilder 對象(但沒有對這些對象調用 TypeBuilder.CreateType)。ReflectionDimension 可用於檢索任何已完成的類型定義,即已加載的類型。

通過指定數組的秩,可以訪問反射中的數組。

  • Type.GetType("MyArray[]") 獲取下限爲 0 的單維數組。

  • Type.GetType("MyArray[*]") 獲取下限未知的單維數組。

  • Type.GetType("MyArray[][]") 獲取二維數組的數組。

  • Type.GetType("MyArray[*,*]")Type.GetType("MyArray[,]") 獲取下限未知的矩形二維數組。

請注意,從運行庫的角度來看,MyArray[] != MyArray[*],但對於多維數組而言,這兩者表示是等效的。也就是說,Type.GetType("MyArray [,]") == Type.GetType("MyArray[*,*]") 的計算結果爲 true

對於 ModuleBuilder.GetTypeMyArray[0..5] 指示大小爲 6 下限爲 0 的單維數組。MyArray[4...] 指示大小未知下限爲 4 的單維數組。

總結

    上面是VS.NET中.NET運行時瞭解類型信息的一些方法和代碼示例,僅供大家參考。有任何建議請MAIL我 [email protected]

發佈了33 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章