這一篇的內容比較複雜,要注意的地方我都寫成註解,所以我們直接來看相關副程式。我們先來看一個最簡單,也是一般在使用組件的方式。
UseHashtable 副程式
''' <summary> ''' 使用一般 Hashtable 方法來顯示 ''' </summary> Private Sub UseHashtable() Console.WriteLine("產生Hashtable") Dim tb As New Hashtable() tb.Add("Hi", "Hello") Console.WriteLine("Hash Count: {0}", tb.Count) Console.WriteLine() Console.ReadLine() End Sub
UseHashtable 副程式執行結果
一般方式,使用Hashtable 產生Hashtable Hash Count: 1
以上是很一般使用 Hashtable 的方式,沒有任何特別之處。但如果我們是要透過動態程式碼的方式來撰寫,就會複雜很多。
使用動態程式碼撰寫 Hashtable 功能
動態程式碼的撰寫要比較了解物件導向,一個步驟一個頻驟建立出你想要的功能,從型別 --> 建構子 --> 方法 ...。''' <summary> ''' 一般而言,建立動態程式碼是在開發及編譯應用程式階段時,需要載入尚未參考的程式碼。 ''' 而非像下例使用的 UseDynamicHashtable 裡的 mscorlib.dll (一般應用程式都會預設載入此組件) ''' 使用動態程式碼,產生 Hashtable,取得及執行add方法、取得Count屬性。 ''' 此範例複雜些,請注意註解及參考MSDN各物件說明 ''' </summary> Private Sub UseDynamicHashtable() Console.WriteLine("使用動態程式產生Hashtable") Dim path As String = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll" Dim asm As Assembly = Assembly.LoadFile(path) ' 取得 Hashtable 型別, 注意下面ci取得建構式 Console.WriteLine(" 取得Hashtable型別") Dim hashType As Type = asm.GetType("System.Collections.Hashtable") Console.WriteLine(" 產生建構式") Dim argType() As Type = Type.EmptyTypes ' 用 ConstructorInfo 來建構這個新型別 ' Type.GetConstructor(...),有三個多載,我們使用第一個來測試 ' GetConstructor(Type()),搜尋其參數符合在指定陣列中(Type())的型別的公用執行個體建構函式。 ' 我們傳入一個「空的型別陣列」 argType() Dim ci As ConstructorInfo = hashType.GetConstructor(argType) ' 呼叫Invoke,產生一個空物件,即一個空的 Hashtable Dim newHash As Object = ci.Invoke(New Object() {}) '' --- 這是另一種寫法 --- '' --- 我們傳入一個含Int32型別的陣列 --- 'Dim argTypes() As Type = New Type() {GetType(System.Int32)} 'Dim ci As ConstructorInfo = hashType.GetConstructor(argTypes) '' --- 注意,因為我們傳入的型別陣列為 Int32,所以產生物件時必須給一個 Int32 值--- '' --- 值可以隨便給,只要是在符合 Int32 範圍即可 --- 'Dim newHash As Object = ci.Invoke(New Object() {1024}) Console.WriteLine(" 取得Add方法") ' 取得型別方法 Dim mi As MethodInfo = hashType.GetMethod("Add") Console.WriteLine(" 執行Add方法") ' 執行取得的方法 ' Public Function Invoke ( obj As Object, parameters As Object() ) As Object ' obj:物件,要在其上叫用方法或建構函式。 ' parameters:叫用方法或建構函式的引數清單。 ' 我要執行 newHash 物件(Hashtable) 的 add 方法,參數是 "Hi", "Hello" mi.Invoke(newHash, New Object() {"Hi", "Hello"}) Console.WriteLine(" 取得Count屬性") ' 取得Count屬性 Dim pi As PropertyInfo = hashType.GetProperty("Count") ' Public Overridable Function GetValue ( obj As Object, index As Object() ) As Object ' obj:其屬性值將被傳回的物件。 ' index:索引屬性的選擇性索引值。非索引屬性的這個值應為 Nothing。 ' 取出 Count 值 Dim count As Integer = CType(pi.GetValue(newHash, Nothing), Integer) Console.WriteLine("Hash Count: {0}", count) Console.WriteLine() Console.WriteLine("靜態成員輸出") ' 使用靜態成員 Dim consoleType As Type = GetType(Console) ' 注意,我們傳入的型別陣列的型別是String Dim WriteLineMeth As MethodInfo = consoleType.GetMethod("WriteLine", New Type() {GetType(String)}) ' 靜態成員可以不需要建立一個物件,傳入 Nothing ' 型別陣列的型別是String,count.ToString() WriteLineMeth.Invoke(Nothing, New Object() {"Hash Count:" & count.ToString()}) ' 如果我們傳入的型別陣列的型別是Int32 'Dim WriteLineMeth As MethodInfo = consoleType.GetMethod("WriteLine", New Type() {GetType(Int32)}) ' 型別陣列的型別是Int32,count (Integer) 直接輸出即可 'WriteLineMeth.Invoke(Nothing, New Object() {count}) End Sub
上面程式碼內容比較多,但看久也會發現「順序」很重要。就是 Step by Step,一、要做什麼;二、要做什麼;…依步驟把內容寫出來。所以說,我們一個封裝很好的 Framework 可以用是非常幸福的事。
UseDynamicHashtable 執行結果
動態程式碼,使用Hashtable 使用動態程式產生Hashtable 取得Hashtable型別 產生建構式 取得Add方法 執行Add方法 取得Count屬性 Hash Count: 1 靜態成員輸出 Hash Count:1
使用動態程式碼,產生 HttpUtility 型別,取得及執行HtmlEncode、HtmlDecode方法
這裡比較難懂,看過上面 UseDynamicHashtable() 之後,我們來看個簡單的。''' <summary> ''' 使用動態程式碼,產生 HttpUtility 型別,取得及執行HtmlEncode、HtmlDecode方法。 ''' </summary> Sub UseDynamicHttpUtility() Dim path As String = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Web.dll" Dim asm As Assembly = Assembly.LoadFile(path) ' 取得型別 Dim utilType As Type = asm.GetType("System.Web.HttpUtility") ' 重點一 ' 取得方法 Dim encode As MethodInfo = utilType.GetMethod("HtmlEncode", New Type() {GetType(System.String)}) Dim decode As MethodInfo = utilType.GetMethod("HtmlDecode", New Type() {GetType(System.String)}) Dim oStr As String = "This is Bruce & Sherry's Happy Family.
有沒有簡單點。
UseDynamicHttpUtility 執行結果
動態程式碼, 使用HttpUtility This is Bruce & Sherry's Happy Family. This is Bruce & Sherry's Happy Family. <picture>. This is Bruce & Sherry's Happy Family.
第一行是原始字串。第二行是 HtmlEncode 的結果。第三行是 HtmlDecode 的結果。
結論
簡單整理出動態程式碼有三個步驟:
- 取得型別
- 取得方法
- 使用方法
這一篇所需要的基礎知識比較多,算是比較難的一篇。加油!
- Sytem.Type.GetMethod 方法 (String)
- System.Type.GetMethod 方法 (String, BindingFlags)
- System.Reflection.MethodBase.Invoke 方法 (Object, Object())
- System.Reflection.MethodBase.Invoke 方法 ((Object, BindingFlags, Binder, Object(), CultureInfo)
- Visual Basic - Reflection, 反映教學筆記(1) 前言
- Visual Basic - Reflection, 反映教學筆記(2) 基礎反映了解
- Visual Basic - Reflection, 反映教學筆記(3) 取得特定屬性
- Visual Basic - Reflection, 反映教學筆記(4) 取得型別的4種方法
- Visual Basic - Reflection, 反映教學筆記(5) 取得型別相關屬性
- Visual Basic - Reflection, 反映教學筆記(6) 暸解MethodBody
- Visual Basic - Reflection, 反映教學筆記(7) - BindingFlags 過濾 Member(成員)
沒有留言:
張貼留言
感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。