通過例子,,淺談反射(Reflection)的應(yīng)用 減小字體 增大字體 作者:佚名 來源:本站整理 發(fā)布時(shí)間:2005-6-15 10:08:50 說明: 應(yīng)該說這篇短文根本算不上什么深入的分析性的文章,所以在標(biāo)題前加上了“淺談”二字,,希望對(duì)于一般的讀者來說,,可以給你一個(gè)相對(duì)直觀些的對(duì)反射的認(rèn)識(shí)。 --2005/05/23 于東莞 在這里對(duì)反射以及反射的概念在最后給出簡(jiǎn)要的解釋,。 一.用來測(cè)試的程序集文件的建立,。 首先你需要建立一個(gè)類庫文件(編譯后擴(kuò)展名為.dll),名字假設(shè)為:reflection_newtest 系統(tǒng)會(huì)默認(rèn)地新建一個(gè)類文件class1,,把它該成我們用來測(cè)試的類person 具體代碼如下:(類的代碼比較簡(jiǎn)單,,這里不做解釋,如有不明之處,,請(qǐng)查看類的相關(guān)文檔.) Public Class person Public firstname As String Public lastname As String Dim m_age As Short Dim m_emailaddress(4) As String Public Sub New() MyBase.new() End Sub Public Sub New(ByVal firstname As String, ByVal lastname As String) Me.firstname = firstname Me.lastname = lastname End Sub Public Property age() As Short Get Return m_age End Get Set(ByVal Value As Short) m_age = Value End Set End Property Public Property emailaddress(ByVal index As Short) As String Get Return m_emailaddress(index) End Get Set(ByVal Value As String) m_emailaddress(index) = Value End Set End Property Sub sendemail(ByVal msg As String, Optional ByVal priorty As Integer = 1) Console.WriteLine("message to " & firstname & " " & lastname) Console.WriteLine("priority " & priorty.ToString) Console.WriteLine(msg) End Sub End Class 二.測(cè)試驗(yàn)證的程序 建立一個(gè)winform的程序,,命名假設(shè)為:testreflection 從工具欄里拖兩個(gè)按鈕,命名為button1,button2. 1.在程序的最上面加入引用: Imports System Imports System.Reflection Imports System.Type 2.在button1的click事件里寫: Dim asm As [Assembly] ‘由于assembly是關(guān)鍵字,,所以要加[] asm = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") ‘這里假設(shè)上面的reflection_newtest文件的位置在G:\練習(xí) 的文件夾,。 Console.WriteLine(asm.FullName) ‘輸出完全限定名 Console.WriteLine(asm.Location) ‘獲取該文件的基本代碼格式的位置 Console.WriteLine(asm.CodeBase) ‘獲取最初指定的程序集的位置,一般來說和Location方法很相似 Dim mo As [Module] ‘遍歷模塊 For Each mo In asm.GetModules Console.WriteLine(mo.FullyQualifiedName) Next Dim ty As Type For Each ty In asm.GetTypes ‘遍歷所有類型的信息 Console.WriteLine(ty.FullName) Next ‘動(dòng)態(tài)加載一個(gè)實(shí)例 Dim o As Object = asm.CreateInstance("reflection_newtest.person") Console.WriteLine("********************") Console.WriteLine(o.GetType.FullName) 說明: 這里的使用都比較簡(jiǎn)單,,請(qǐng)繼續(xù)往下看! 3.建立測(cè)試的過程 '獲取遍歷的類型,,這里使用了系統(tǒng)類庫文件mscorlib.dll Private Sub testtypeenumeration() Dim asm As [Assembly] = Reflection.Assembly.Load("mscorlib") Dim t As Type For Each t In asm.GetExportedTypes ‘對(duì)于當(dāng)前的文件的測(cè)試 If t.IsClass Then ‘如果是類 Console.WriteLine(t.Name & "(class)") ElseIf t.IsEnum Then ‘如果是枚舉 Console.WriteLine(t.Name & "(enum)") ElseIf t.IsValueType Then ‘如果是值類型 Console.WriteLine(t.Name & "(structure)") ElseIf t.IsInterface Then ‘如果是接口 Console.WriteLine(Name & "(interface)") Else ‘其他 '沒做處理 End If Next End Sub '獲取某一類型的所有信息(這里以string為例) ‘從上面的load與type.gettype可見,,他們都是創(chuàng)建assembly的方式 Private Sub testatypememberinfo1() Dim stringtype As Type = Type.GetType("System.String") '獲取指定名稱的系統(tǒng)類型,也可以使用type.gettype(string) Dim minfos() As MemberInfo ‘類型數(shù)組 Dim mi As MemberInfo minfos = stringtype.GetMembers For Each mi In minfos Console.WriteLine(mi.Name) Next '獲得公共的非共享的并且是繼承的成員 minfos = stringtype.GetMembers(BindingFlags.Public Or BindingFlags.Instance Or BindingFlags.DeclaredOnly) ‘為了便于看清楚輸出,,做了間隔 Console.WriteLine("*********************") For Each mi In minfos Console.WriteLine(mi.Name) Next ‘同樣的間隔設(shè)置 Console.WriteLine("*********************") '獲取所有方法 For Each mi In stringtype.GetMethods Console.WriteLine(mi.Name) Next End Sub '使用特定的顯示某一種類型的方法 Private Sub testatypememberinfo() Dim stringtype As Type = Type.GetType("System.String") '獲取指定名稱的系統(tǒng)類型 ‘對(duì)于特定類型的屬性的遍歷 Dim pinfos() As PropertyInfo = stringtype.GetProperties Dim mi As MemberInfo For Each mi In pinfos Console.WriteLine(mi.Name) Next End Sub '使用findmember方法對(duì)類型的遍歷1 Private Sub testfindmember1() Dim stringtype As Type = Type.GetType("System.String") ‘對(duì)于findmembers方法來說,,它的參數(shù)分別為要獲得的類型(可用or組合),篩選條件(可用or組合),, 委托函數(shù),,傳遞給委托函數(shù)的參數(shù)。 Dim minfos() As MemberInfo = stringtype.FindMembers(MemberTypes.Method _ Or MemberTypes.Property, BindingFlags.Instance Or BindingFlags.Public, _ AddressOf filterbyname1, "C") Dim mi As MemberInfo For Each mi In minfos Console.WriteLine(mi.Name) Next End Sub '委托函數(shù)一:篩選那些是以C開頭的公共的實(shí)例的方法和屬性(這個(gè)函數(shù)一旦返回true,,意味著是符合要求的) Private Function filterbyname1(ByVal m As MemberInfo, ByVal filtercriteria As Object) As Boolean '如果成員名稱以篩選函數(shù)的第2個(gè)參數(shù)開始,,則返回true If m.Name.StartsWith(filtercriteria.ToString) Then Return True End If End Function '使用findmember方法對(duì)類型的遍歷2 Private Sub testfindmember2() Dim returntype As Type = Type.GetType("System.Int32") Dim minfos() As MemberInfo = returntype.FindMembers(MemberTypes.Method Or MemberTypes.Property, _ BindingFlags.Instance Or BindingFlags.Public, AddressOf filterbyname2, returntype) Dim mi As MemberInfo For Each mi In minfos Console.WriteLine(mi.Name) Next End Sub '委托函數(shù)二 Private Function filterbyname2(ByVal m As MemberInfo, ByVal filtercriteria As Object) As Boolean If m.MemberType = MemberTypes.Property Then Dim pi As PropertyInfo = CType(m, PropertyInfo) Return (pi.PropertyType Is filtercriteria) '如果該屬性的類型與第2個(gè)參數(shù)相同則返回true ElseIf m.MemberType = MemberTypes.Method Then Dim mi As MethodInfo = CType(m, MethodInfo) Return (mi.ReturnType Is filtercriteria) '如果該方法的返回類型與第2個(gè)參數(shù)相同則返回true End If End Function '關(guān)于重載函數(shù)的調(diào)用 Private Sub testoverloadmemberinfo() Dim stringtype As Type = Type.GetType("System.String") '一個(gè)類型數(shù)組 Dim argtypes() As Type = {Type.GetType("System.String"), Type.GetType("System.String")} Dim mi As MemberInfo = stringtype.GetMethod("Compare", argtypes) Console.WriteLine(mi.Name) End Sub '枚舉參數(shù)類型 Private Sub testcallingsyntax() Dim stringtype As Type = Type.GetType("System.String") Dim mi As MethodInfo = stringtype.GetMethod("Copy") Dim pinfos() As ParameterInfo = mi.GetParameters Dim i As Integer '列出參數(shù)和參數(shù)的類型,中間用/連接 For i = 0 To pinfos.GetUpperBound(0) Console.WriteLine(pinfos(i).Name & "/" & pinfos(i).ParameterType.ToString) Next End Sub '使用反射創(chuàng)建實(shí)例并給屬性賦值 Private Sub testreadwriteproperties() Try Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Dim m As Object = Activator.CreateInstance(ty) Dim pi As PropertyInfo = ty.GetProperty("age") pi.SetValue(m, 5S, Nothing) '一定要指定賦值的類型,,如是short類型,一定要加s Console.WriteLine(pi.GetValue(m, Nothing)) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub '測(cè)試字符串屬性(且含參數(shù)) Private Sub testreadwritepropertytieswithargs() Try Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Dim m As Object = Activator.CreateInstance(ty) Dim pi As PropertyInfo = ty.GetProperty("emailaddress") Dim params() As Object = {1S} '注意參數(shù)類型的嚴(yán)格匹配 pi.SetValue(m, " 321 north street ", params) 321 north street ", params) Console.WriteLine(pi.GetValue(m, params)) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub '使用invoke方法測(cè)試過程 Private Sub testinvokemethod() Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Dim m As Object = Activator.CreateInstance(ty) Dim mi As MethodInfo = ty.GetMethod("sendemail") '定義過程的參數(shù)數(shù)組 Dim params(mi.GetParameters.Length - 1) As Object Try params(0) = "this is message" params(1) = 3 '觸發(fā)過程 mi.Invoke(m, params) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub '使用invokemember方法測(cè)試過程 Private Sub testinvokemember() Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Dim m As Object = Activator.CreateInstance(ty) Dim args() As Object = {"francesco"} Try '設(shè)置firstname字段值 ty.InvokeMember("firstname", BindingFlags.SetField, Nothing, m, args) '讀取firstname字段值,,這個(gè)時(shí)候不用最后一個(gè)參數(shù) Dim value As Object = ty.InvokeMember("firstname", BindingFlags.GetField, Nothing, m, Nothing) Console.WriteLine(value.ToString) Dim args2() As Object = {35S} '注意這里的數(shù)組元素的類型一定要嚴(yán)格匹配short類型, '設(shè)置屬性值,,參數(shù)意味著是屬性的參數(shù) ty.InvokeMember("age", BindingFlags.SetProperty, Nothing, m, args2) '讀取屬性值 Dim value1 As Object = ty.InvokeMember("age", BindingFlags.GetProperty, Nothing, m, Nothing) Console.WriteLine(value1.ToString) Dim args3() As Object = {"this is a message", 2} '觸發(fā)過程 ty.InvokeMember("sendemail", BindingFlags.InvokeMethod, Nothing, m, args3) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub ‘/////////////////////////////////////////////////////////// '動(dòng)態(tài)地創(chuàng)建對(duì)象(使用默認(rèn)地構(gòu)造函數(shù)) Private Sub testobjectcreation1() Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Try Dim m As Object = Activator.CreateInstance(ty) Console.WriteLine("A {0} object has been created ", m.GetType.Name) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub '使用帶參數(shù)的方法(使用帶參數(shù)的構(gòu)造函數(shù)) Private Sub testobjectcreation2() Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Dim params() As Object = {"Joe", "Doe"} Try Dim o As Object = System.Activator.CreateInstance(ty, params) Console.WriteLine(o.GetType.Name) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub '使用調(diào)用構(gòu)造函數(shù)的方法來創(chuàng)建對(duì)象(實(shí)例)這個(gè)方法相對(duì)來說比較煩瑣和麻煩。 Private Sub testobjectcreation3() Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\練習(xí)\reflection_newtest\bin\reflection_newtest.dll") Dim ty As Type = asm.GetType("reflection_newtest.person") Dim types() As Type = {GetType(System.String), GetType(String)} Dim ci As ConstructorInfo = ty.GetConstructor(types) '獲得這個(gè)有兩個(gè)字符串參數(shù)的構(gòu)造函數(shù)的信息 Dim params() As Object = {"Joe", "Doe"} '用來初始化的數(shù)組 Dim o As Object = ci.Invoke(params) '執(zhí)行這個(gè)構(gòu)造函數(shù) Console.WriteLine(o.GetType.Name) End Sub 4. button2的click事件中寫:(該操作就是驗(yàn)證所有的測(cè)試過程,,為了分辨出是哪個(gè)過程的結(jié)果,,把其他的都暫時(shí)注釋掉了。你可以根據(jù)需要來消除注釋,。) 'testtypeenumeration() 'testatypememberinfo1() 'testatypememberinfo2() 'testfindmember1() 'testfindmember2() testoverloadmemberinfo() 'testcallingsyntax() 'testreadwriteproperties() 'testreadwritepropertytieswithargs() 'testinvokemethod() 'testinvokemember() 'testobjectcreation1() 'testobjectcreation2() 'testobjectcreation3() 說明:這里不多做過多地解釋,,代碼中有比較完整的注釋。如果有什么疏漏和錯(cuò)誤,,請(qǐng)指出,!謝謝! 相關(guān)名詞的簡(jiǎn)單說明: 反射(Reflection):.Net中獲取運(yùn)行時(shí)類型信息的方式 程序集(Assembly):編譯后的.dll和exe文件,??梢垣@得正在運(yùn)行的裝配件信息,也可以動(dòng)態(tài)的加載裝配件,,以及在裝配件中查找類型信息,,并創(chuàng)建該類型的實(shí)例。 類型(type):這里的類型區(qū)分于值類型與引用類型中的類型,,它包括類,,枚舉,值類型,,接口等,。 |
|