Visual Basic - Reflection, 反映教學筆記(7) - BindingFlags 過濾 Member(成員)

我們再談談Type 的 Member,我們前面寫過一段簡單取得 Member 的程式碼:

01''' <summary>
02''' 簡單測試及顯示型別 GetMembers() 方法
03''' </summary>
04''' <param name="type">型別 (即Type) 物件</param>
05Private Sub ShowGetMembers(type As Type)
06    Console.WriteLine("取得型別Members")
07    For Each mi As MemberInfo In type.GetMembers()
08        Console.WriteLine("    Member的 Type 及 名稱")
09        Console.WriteLine("          {0}:{1}", mi.MemberType, mi.Name)
10        ShowMemberType(mi)
11    Next
12    Console.WriteLine()
13    Console.ReadLine()
14End Sub

基本上,這沒什麼問題。但如果我想的資訊只需要「特定成員呢?」這時候我們就必須設定一個 BindingFlags 列舉型別給 type.GetMembers(),BindingFlags 指定控制繫結的旗標和由反映為引導的成員和型別搜尋方式。

這些 BindingFlags 會控制在叫用 (Invoke)、建立、取得、設定和尋找成員和型別的 System、System.Reflection 和 System.Runtime 命名空間中眾多類別的繫結。 

BindingFlags 用於下列 Type 方法和其他地方,例如,

  • MethodBase.Invoke
  • GetMembers 
  • GetEvents 
  • InvokeMember 
  • Activator.CreateInstance 
  • GetConstructor 
  • GetConstructors 
  • GetMethod 
  • GetMethods 
  • GetField 
  • GetFields 
  • GetEvent 
  • GetProperty 
  • GetProperties 
  • GetMember 
  • FindMembers 

其中 InvokeMember 和 GetMethod 特別重要。


ShowMemberFilterFlags 副程式

01#Region "顯示Member方法,但使用 BindingFlags 過濾成員"
02    ''' <summary>
03    ''' 由 BindingFlags 過濾所要取得的成員,你可以改變bfs1,2後面的參數來觀察
04    ''' </summary>
05    Private Sub ShowMemberFilterFlags()
06        ' 由一般型別來測試
07        Console.WriteLine("由GetType(String)取得")
08        Dim t As Type = GetType(String)
09 
10        ' 設定想要的成員
11        ' 重點:可以使用 Or, And … 等使用多個列舉
12        Dim bfs1 As BindingFlags = BindingFlags.Public Or
13                                     BindingFlags.Instance Or
14                                     BindingFlags.Static
15 
16        Console.WriteLine("BindingFlags條件為:Public、Instance、Static")
17        ShowMemberInfo(t.GetMembers(bfs1))
18        Console.WriteLine()
19        Console.ReadLine()
20 
21        ' 由載入組件來測試
22        Console.WriteLine("由System.ServiceProcess.dll載入組件")
23        Dim path As String = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.ServiceProcess.dll"
24        Dim asm As Assembly = Assembly.LoadFrom(path)
25 
26        Dim bfs2 As BindingFlags = BindingFlags.DeclaredOnly Or
27                                     BindingFlags.Public Or
28                                     BindingFlags.Instance
29 
30        Console.WriteLine(asm.FullName)
31        ' 停一下,不然看不到資訊,太長了
32        Console.ReadLine()
33 
34        Console.WriteLine()
35        Dim types() As Type = asm.GetTypes()
36        For Each type As Type In types
37            Console.WriteLine("Type:{0}", type.Name)
38            Console.WriteLine("     BindingFlags條件為:DeclaredOnly、Public、Instance")
39            ShowMemberInfo(type.GetMembers(bfs2))
40        Next
41    End Sub
42 
43    ''' <summary>
44    ''' 顯示 MemberInfo 物件相關資訊
45    ''' </summary>
46    ''' <param name="mi">MemberInfo 陣列物件</param>
47    ''' <remarks></remarks>
48    Private Sub ShowMemberInfo(mi() As MemberInfo)
49        For Each m As MemberInfo In mi
50            Console.WriteLine("         Member: {0}, Type: {1}", m.Name, m.MemberType)
51        Next
52    End Sub
53#End Region

我們執行兩次,兩次給的 BindingFlags 不一樣,你可以自由改變載入的 Type 和 BindingFlags 去測試看看。然後透過 ShowMemberInfo() 來顯示成員名稱及成員型別。

ShowMemberFilterFlags 副程式執行結果

先由內建型別開始,我們指定為 String 型別。

由GetType(String)取得
BindingFlags條件為:Public、Instance、Static
         Member: Join, Type: Method
         Member: Equals, Type: Method
         Member: op_Equality, Type: Method
         Member: op_Inequality, Type: Method
         Member: get_Chars, Type: Method
         Member: CopyTo, Type: Method
         Member: ToCharArray, Type: Method
         Member: IsNullOrEmpty, Type: Method
         Member: IsNullOrWhiteSpace, Type: Method
         Member: GetHashCode, Type: Method
         Member: get_Length, Type: Method
         Member: Split, Type: Method
         Member: Substring, Type: Method
         Member: Trim, Type: Method
         Member: TrimStart, Type: Method
         Member: TrimEnd, Type: Method
         Member: IsNormalized, Type: Method
         Member: Normalize, Type: Method
         Member: Compare, Type: Method
         ... 略 ...

以上結果是整理過的內容,不然你應該看到很多重覆內容的才對,原因很簡單,例如 String.Join() 它的重載就有五個之多,所以你會看到五次「Member: Join, Type: Method」才對。

載入一個已存在的組件,來測試看看。

由System.ServiceProcess.dll載入組件
System.ServiceProcess, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
... 略,以下為最後五筆 ...
Type:DeferredHandlerDelegate
     BindingFlags條件為:DeclaredOnly、Public、Instance
         Member: Invoke, Type: Method
         Member: BeginInvoke, Type: Method
         Member: EndInvoke, Type: Method
         Member: .ctor, Type: Constructor
Type:DeferredHandlerDelegateCommand
     BindingFlags條件為:DeclaredOnly、Public、Instance
         Member: Invoke, Type: Method
         Member: BeginInvoke, Type: Method
         Member: EndInvoke, Type: Method
         Member: .ctor, Type: Constructor
Type:DeferredHandlerDelegateAdvanced
     BindingFlags條件為:DeclaredOnly、Public、Instance
         Member: Invoke, Type: Method
         Member: BeginInvoke, Type: Method
         Member: EndInvoke, Type: Method
         Member: .ctor, Type: Constructor
Type:UnsafeNativeMethods
     BindingFlags條件為:DeclaredOnly、Public、Instance
Type:ServiceNameConverter
     BindingFlags條件為:DeclaredOnly、Public、Instance
         Member: CanConvertFrom, Type: Method
         Member: ConvertFrom, Type: Method
         Member: GetStandardValues, Type: Method
         Member: GetStandardValuesExclusive, Type: Method
         Member: GetStandardValuesSupported, Type: Method
         Member: .ctor, Type: Constructor

這邊我們只要了解,我們可以使用 BindingFlags 來改變我們搜尋出來的結果即可,細部的舉列值,請參考 MSDN。

參考資料

沒有留言:

張貼留言

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