说明:
应该说这篇短文根本算不上什么深入的分析性的文章,所以在标题前加上了“浅谈”二字,希望对于一般的读者来说,可以给你一个相对直观些的对反射的认识。
--
在这里对反射以及反射的概念在最后给出简要的解释。
一.用来测试的程序集文件的建立。
首先你需要建立一个类库文件(编译后扩展名为.dll),名字假设为:reflection_newtest
系统会默认地新建一个类文件class1,把它该成我们用来测试的类person
具体代码如下:(类的代码比较简单,这里不做解释,如有不明之处,请查看类的相关文档.)
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()
Public Sub New()
Public Sub New()
MyBase.new()
End Sub
Public Sub New(ByVal firstname As String, ByVal lastname As String)
Public Sub New(ByVal firstname As String, ByVal lastname As String)
Public Sub New(ByVal firstname As String, ByVal lastname As String)
Me.firstname = firstname
Me.lastname = lastname
End Sub
Public Property age() As Short
Public Property age() As Short
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
二.测试验证的程序
二.测试验证的程序
二.测试验证的程序
建立一个winform的程序,命名假设为:testreflection
从工具栏里拖两个按钮,命名为button1,button2.
1.在程序的最上面加入引用:
Imports System
Imports System.Reflection
Imports System.Type
2.在button1的click事件里写:
Dim asm As [Assembly] ‘由于assembly是关键字,所以要加[]
Dim asm As [Assembly] ‘由于assembly是关键字,所以要加[]
Dim asm As [Assembly] ‘由于assembly是关键字,所以要加[]
asm = Reflection.Assembly.LoadFrom("G:\练习\reflection_newtest\bin\reflection_newtest.dll") ‘这里假设上面的reflection_newtest文件的位置在G:\练习 的文件夹。
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
‘动态加载一个实例
Dim o As Object = asm.CreateInstance("reflection_newtest.person")
Console.WriteLine("********************")
Console.WriteLine(o.GetType.FullName)
说明: 这里的使用都比较简单,请继续往下看!
3.建立测试的过程
'获取遍历的类型,这里使用了系统类库文件mscorlib.dll
Private Sub testtypeenumeration()
Dim asm As [Assembly] = Reflection.Assembly.Load("mscorlib")
Dim t As Type
For Each t In asm.GetExportedTypes ‘对于当前的文件的测试
If t.IsClass Then ‘如果是类
Console.WriteLine(t.Name & "(class)")
ElseIf t.IsEnum Then ‘如果是枚举
ElseIf t.IsEnum Then ‘如果是枚举
ElseIf t.IsEnum Then ‘如果是枚举
Console.WriteLine(t.Name & "(enum)")
ElseIf t.IsValueType Then ‘如果是值类型
ElseIf t.IsValueType Then ‘如果是值类型
ElseIf t.IsValueType Then ‘如果是值类型
Console.WriteLine(t.Name & "(structure)")
ElseIf t.IsInterface Then ‘如果是接口
ElseIf t.IsInterface Then ‘如果是接口
ElseIf t.IsInterface Then ‘如果是接口
Console.WriteLine(Name & "(interface)")
Else ‘其他
'没做处理
End If
Next
End Sub
'获取某一类型的所有信息(这里以string为例)
‘从上面的load与type.gettype可见,他们都是创建assembly的方式
Private Sub testatypememberinfo1()
Dim stringtype As Type = Type.GetType("System.String") '获取指定名称的系统类型,也可以使用type.gettype(string)
Dim minfos() As MemberInfo ‘类型数组
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
‘同样的间隔设置
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") '获取指定名称的系统类型
‘对于特定类型的属性的遍历
Dim pinfos() As PropertyInfo = stringtype.GetProperties
Dim mi As MemberInfo
For Each mi In pinfos
Console.WriteLine(mi.Name)
Next
End Sub
'使用findmember方法对类型的遍历1
Private Sub testfindmember1()
Dim stringtype As Type = Type.GetType("System.String")
‘对于findmembers方法来说,它的参数分别为要获得的类型(可用or组合),筛选条件(可用or组合),
委托函数,传递给委托函数的参数。
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
'委托函数一:筛选那些是以C开头的公共的实例的方法和属性(这个函数一旦返回true,意味着是符合要求的)
Private Function filterbyname1(ByVal m As MemberInfo, ByVal filtercriteria As Object) As Boolean
'如果成员名称以筛选函数的第2个参数开始,则返回true
If m.Name.StartsWith(filtercriteria.ToString) Then
Return True
End If
End Function
'使用findmember方法对类型的遍历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
'委托函数二
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个参数相同则返回true
ElseIf m.MemberType = MemberTypes.Method Then
Dim mi As MethodInfo = CType(m, MethodInfo)
Return (mi.ReturnType Is filtercriteria) '如果该方法的返回类型与第2个参数相同则返回true
End If
End Function
'关于重载函数的调用
Private Sub testoverloadmemberinfo()
Dim stringtype As Type = Type.GetType("System.String")
'一个类型数组
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
'枚举参数类型
Private Sub testcallingsyntax()
Dim stringtype As Type = Type.GetType("System.String")
Dim stringtype As Type = Type.GetType("System.String")
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
'列出参数和参数的类型,中间用/连接
For i = 0 To pinfos.GetUpperBound(0)
Console.WriteLine(pinfos(i).Name & "/" & pinfos(i).ParameterType.ToString)
Next
End Sub
End Sub
End Sub
'使用反射创建实例并给属性赋值
Private Sub testreadwriteproperties()
Try
Try
Try
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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))
Console.WriteLine(pi.GetValue(m, Nothing))
Console.WriteLine(pi.GetValue(m, Nothing))
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
'测试字符串属性(且含参数)
Private Sub testreadwritepropertytieswithargs()
Try
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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} '注意参数类型的严格匹配
pi.SetValue(m, "321 north street", params)
Console.WriteLine(pi.GetValue(m, params))
Console.WriteLine(pi.GetValue(m, params))
Console.WriteLine(pi.GetValue(m, params))
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
'使用invoke方法测试过程
Private Sub testinvokemethod()
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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")
'定义过程的参数数组
Dim params(mi.GetParameters.Length - 1) As Object
Try
params(0) = "this is message"
params(1) = 3
'触发过程
mi.Invoke(m, params)
Catch ex As Exception
Catch ex As Exception
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
'使用invokemember方法测试过程
Private Sub testinvokemember()
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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
'设置firstname字段值
ty.InvokeMember("firstname", BindingFlags.SetField, Nothing, m, args)
'读取firstname字段值,这个时候不用最后一个参数
Dim value As Object = ty.InvokeMember("firstname", BindingFlags.GetField, Nothing, m, Nothing)
Console.WriteLine(value.ToString)
Dim args2() As Object = {35S} '注意这里的数组元素的类型一定要严格匹配short类型,
'设置属性值,参数意味着是属性的参数
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}
'触发过程
ty.InvokeMember("sendemail", BindingFlags.InvokeMethod, Nothing, m, args3)
Catch ex As Exception
Catch ex As Exception
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
‘///////////////////////////////////////////////////////////
'动态地创建对象(使用默认地构造函数)
Private Sub testobjectcreation1()
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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
'使用带参数的方法(使用带参数的构造函数)
Private Sub testobjectcreation2()
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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
'使用调用构造函数的方法来创建对象(实例)这个方法相对来说比较烦琐和麻烦。
Private Sub testobjectcreation3()
Dim asm As [Assembly] = Reflection.Assembly.LoadFrom("G:\练习\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) '获得这个有两个字符串参数的构造函数的信息
Dim params() As Object = {"Joe", "Doe"} '用来初始化的数组
Dim o As Object = ci.Invoke(params) '执行这个构造函数
Console.WriteLine(o.GetType.Name)
End Sub
4. button2的click事件中写:(该操作就是验证所有的测试过程,为了分辨出是哪个过程的结果,把其他的都暂时注释掉了。你可以根据需要来消除注释。)
'testtypeenumeration()
'testatypememberinfo1()
'testatypememberinfo2()
'testfindmember1()
'testfindmember2()
testoverloadmemberinfo()
'testcallingsyntax()
'testreadwriteproperties()
'testreadwritepropertytieswithargs()
'testinvokemethod()
'testinvokemember()
'testobjectcreation1()
'testobjectcreation2()
'testobjectcreation3()
说明:这里不多做过多地解释,代码中有比较完整的注释。如果有什么疏漏和错误,请指出!谢谢!
相关名词的简单说明:
反射(Reflection):.Net中获取运行时类型信息的方式
程序集(Assembly):编译后的.dll和exe文件。可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。
类型(type):这里的类型区分于值类型与引用类型中的类型,它包括类,枚举,值类型,接口等。