Visual Basic - Reflection, 反映教學筆記(5) 取得型別相關屬性

我們在上一篇「Visual Basic - Reflection, 反映教學筆記(4) 取得型別的4種方法」中,在 Object 取得型別裡,給了一段不算短的程式碼,主要是顯示別型相關訊息。這一篇主要解釋那一段程式碼。此副程式的主要進入點為 ShowTypeAttributes()。

ShowTypeAttributes 副程式

01''' <summary>
02''' 直接顯示型別相關資訊
03''' </summary>
04Sub ShowTypeAttributes()
05    Dim type As Type = GetType(String)
06    ' 取得型別屬性
07    GetTypeAttribute(type)
08    ' 取得型別自訂屬性
09    ShowCustomAttribute(type)
10    ' 取得型別 Getxxx
11    ShowTypeGetxxx(type)
12End Sub

這裡很簡單,只是取得型別後,我想顯示一些型別的屬性、方法。我把這些方法另外再分為三個小副程式。

GetTypeAttribute 副程式

01''' <summary>
02''' 由物件取得型別後,額外顯示相關屬性
03''' </summary>
04''' <param name="type">Type (型別)</param>
05Sub GetTypeAttribute(type As Type)
06    Console.WriteLine("型別的屬性")
07    Console.WriteLine("Assembly : {0}", type.Assembly)
08    Console.WriteLine("AQN : {0}", type.AssemblyQualifiedName)
09    Console.WriteLine("Attributes: {0}", type.Attributes)
10    Console.WriteLine("BaseType: {0}", type.BaseType)
11    Console.WriteLine("FullName: {0}", type.FullName)
12    Console.WriteLine("HasElementType: {0}", type.HasElementType)
13    Console.WriteLine("IsAbstract: {0}", type.IsAbstract)
14    Console.WriteLine("IsByRef: {0}", type.IsByRef)
15    Console.WriteLine("IsClass: {0}", type.IsClass)
16    Console.WriteLine("IsEnum: {0}", type.IsEnum)
17    Console.WriteLine("IsGenericType: {0}", type.IsGenericType)
18    Console.WriteLine("IsInterface: {0}", type.IsInterface)
19    Console.WriteLine("IsMarshalByRef: {0}", type.IsMarshalByRef)
20    Console.WriteLine("IsNotPublic: {0}", type.IsNotPublic)
21    Console.WriteLine("IsPrimitive: {0}", type.IsPrimitive)
22    Console.WriteLine("IsPublic: {0}", type.IsPublic)
23    Console.WriteLine("IsSealed: {0}", type.IsSealed)
24    Console.WriteLine("IsValueType: {0}", type.IsValueType)
25    Console.WriteLine("IsVisible: {0}", type.IsVisible)
26    Console.WriteLine("Module: {0}", type.Module)
27    Console.WriteLine("Name: {0}", type.Name)
28    Console.WriteLine("Namespace: {0}", type.Namespace)
29    Console.WriteLine()
30    Console.ReadLine()
31End Sub

我們列出前一篇文章裡所提到的 Isxxx 屬性,這一類 Isxxx 都是回傳 Boolean 值,我建議打開 MSDN 裡的 System.Type 屬性對照著看,會比較清楚。

ShowCustomAttribute 副程式


01''' <summary>
02''' 由傳入參數,顯示相關型別相關屬性
03''' </summary>
04''' <param name="type">Type (型別)</param>
05Sub ShowCustomAttribute(type As Type)
06    Console.WriteLine("取得類別屬性:")
07    For Each attr As Attribute In type.GetCustomAttributes(True)
08        Console.WriteLine("  {0}", attr.GetType.Name)
09    Next
10    Console.WriteLine()
11End Sub

這裡注意我們使用的 type.GetCustomAttributes(True) 必須傳入一個 Boolean 值,true 表示要搜尋這個成員的繼承鏈結以尋找屬性,否則為 false。 對於屬性和事件來說,會忽略這個參數。若要搜尋屬性 (Property) 和事件之屬性 (Attribute) 繼承鏈結,請使用 Attribute.GetCustomAttributes 方法的適當多載。

ShowTypeGetxxx 副程式

這裡就精彩了。

ShowTypeGetxxx 又是另一個進入點,然後在裡面分別呼叫其他 7 支副程式,顯示此型別的屬性、巢狀型別、成員、建構子、事件、欄位、方法。

001#Region "顯示型別相關 Getxxx 方法"
002 
003    ''' <summary>
004    ''' 呼叫型別相關 Getxxx 測試方法
005    ''' </summary>
006    ''' <param name="type">型別 (即Type) 物件</param>
007    Sub ShowTypeGetxxx(type As Type)
008        ' 顯示型別屬性
009        ShowGetProperties(type)
010        ' 顯示型別巢狀型別
011        ShowGetNestedTypes(type)
012        ' 顯示型別成員
013        ShowGetMembers(type)
014        ' 顯示型別建構子
015        ShowGetConstructors(type)
016        ' 顯示型別事件
017        ShowGetEvent(type)
018        ' 顯示型別欄位
019        ShowGetFields(type)
020        ' 顯示型別方法
021        ShowGetMethods(type)
022    End Sub
023 
024    ''' <summary>
025    ''' 簡單測試及顯示型別的屬性(Properties)
026    ''' </summary>
027    ''' <param name="type">型別 (即Type) 物件</param>
028    Private Sub ShowGetProperties(type As Type)
029        Console.WriteLine("取得型別Properties")
030        For Each pi As PropertyInfo In type.GetProperties
031            Console.WriteLine("{0}", pi.Name)
032        Next
033        Console.WriteLine()
034        Console.ReadLine()
035    End Sub
036 
037    ''' <summary>
038    ''' 簡單測試及顯示型別的NestedTypes
039    ''' </summary>
040    ''' <param name="type">型別 (即Type) 物件</param>
041    Private Sub ShowGetNestedTypes(type As Type)
042        Console.WriteLine("取得型別NestedTypes")
043        For Each gnt As Type In type.GetNestedTypes
044            Console.WriteLine("{0}", gnt.Name)
045        Next
046        Console.WriteLine()
047        Console.ReadLine()
048    End Sub
049 
050    ''' <summary>
051    ''' 簡單測試及顯示型別 GetMembers() 方法
052    ''' </summary>
053    ''' <param name="type">型別 (即Type) 物件</param>
054    Private Sub ShowGetMembers(type As Type)
055        Console.WriteLine("取得型別Members")
056        For Each mi As MemberInfo In type.GetMembers()
057            Console.WriteLine("    Member的 Type 及 名稱")
058            Console.WriteLine("          {0}:{1}", mi.MemberType, mi.Name)
059            ShowMemberType(mi)
060        Next
061        Console.WriteLine()
062        Console.ReadLine()
063    End Sub
064 
065    ''' <summary>
066    ''' 簡單測試及顯示MemberInfo裡MemberType成員,目前只讓 ShowGetMembers 呼叫
067    ''' </summary>
068    ''' <param name="mi">MemberInfo物件</param>
069    Private Sub ShowMemberType(mi As MemberInfo)
070        ' MemberInfo 可藉由 MemberTypes 來判斷出型別的不同成員,注意,都是public。
071        ' 簡單測試 MemberTypes.Property
072        Select Case mi.MemberType
073            Case MemberTypes.Constructor
074            Case MemberTypes.Custom
075            Case MemberTypes.Event
076            Case MemberTypes.Field
077            Case MemberTypes.Method
078            Case MemberTypes.NestedType
079            Case MemberTypes.Property
080                Dim pi As PropertyInfo = CType(mi, PropertyInfo)
081                Console.WriteLine("          Property Type: {0}", pi.PropertyType.Name)
082            Case MemberTypes.TypeInfo
083            Case MemberTypes.All
084            Case Else
085                Console.WriteLine("什麼!完全沒有符合的成員!")
086        End Select
087    End Sub
088 
089    ''' <summary>
090    ''' 簡單測試及顯示型別 GetConstructors 方法
091    ''' </summary>
092    ''' <param name="type">型別 (即Type) 物件</param>
093    Sub ShowGetConstructors(type As Type)
094        Console.WriteLine("取得型別Constructors")
095        For Each ci As ConstructorInfo In type.GetConstructors
096            Console.WriteLine("    IsSecuritySafeCritical: {0}", ci.IsSecuritySafeCritical)
097        Next
098        Console.WriteLine()
099        Console.ReadLine()
100    End Sub
101 
102    ''' <summary>
103    ''' 簡單測試及顯示型別 GetEvents 方法
104    ''' </summary>
105    ''' <param name="type">型別 (即Type) 物件</param>
106    Sub ShowGetEvent(type As Type)
107        Console.WriteLine("取得型別Events")
108        For Each ei As EventInfo In type.GetEvents
109            Console.WriteLine("    DeclaringType: {0}", ei.DeclaringType)
110        Next
111        Console.WriteLine()
112        Console.ReadLine()
113    End Sub
114 
115    ''' <summary>
116    ''' 簡單測試及顯示型別 GetFields 方法
117    ''' </summary>
118    ''' <param name="type">型別 (即Type) 物件</param>
119    Sub ShowGetFields(type As Type)
120        Console.WriteLine("取得型別Fields")
121        For Each fi As FieldInfo In type.GetFields
122            Console.WriteLine("    FieldType: {0}", fi.FieldType)
123        Next
124        Console.WriteLine()
125        Console.ReadLine()
126    End Sub
127 
128    ''' <summary>
129    ''' 簡單測試及顯示型別 GetMethods 方法
130    ''' </summary>
131    ''' <param name="type">型別 (即Type) 物件</param>
132    Sub ShowGetMethods(type As Type)
133        Console.WriteLine("取得型別Methods")
134        For Each mi As MethodInfo In type.GetMethods
135            Console.WriteLine("Method: {0}, IsPublic: {1}", mi.GetBaseDefinition.Name, mi.IsPublic)
136        Next
137        Console.WriteLine()
138        Console.ReadLine()
139    End Sub
140 
141#End Region


  • 顯示型別屬性,ShowGetProperties(type)  --> PropertyInfo
  • 顯示型別巢狀型別,ShowGetNestedTypes(type)  --> Type
  • 顯示型別成員,ShowGetMembers(type)  --> MemberInfo
  • 顯示型別建構子,ShowGetConstructors(type)  --> ConstructorInfo
  • 顯示型別事件,ShowGetEvent(type)  --> EventInfo
  • 顯示型別欄位,ShowGetFields(type)  --> FieldInfo
  • 顯示型別方法,ShowGetMethods(type) --> MethodInfo
不知道你有沒有發現,在以上 7 支副程式中,我們都是使用 Info 結尾的類別(除NestedTypes)來接收型別傳過來的資訊。再回去看看以上副程式,雖然很多,但其實動作都是一樣的。你想要「屬性」資訊,那就用 PropertyInfo 來接收資訊,每個你想要的資訊內容都一個對應的 *Info 類別( 請參考 Reflection 類別 ),記住這一點,那以上的副程式看起來比會簡單許多。

參考資料

  1. System.Type 屬性
  2. GetCustomAttributes
  3. Attribute.GetCustomAttributes
  4. Reflection 類別 (以這篇而言,是找 *Info 類別來看)
  5. Visual Basic - Reflection, 反映教學筆記(1) 前言
  6. Visual Basic - Reflection, 反映教學筆記(2) 基礎反映了解
  7. Visual Basic - Reflection, 反映教學筆記(3) 取得特定屬性
  8. Visual Basic - Reflection, 反映教學筆記(4) 取得型別的4種方法

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。