通过例子,浅谈反射(Reflection)的应用

                                                          通过例子,浅谈反射(Reflection)的应用


【转载,目的是自己学习翻阅使用方便】


说明:
应该说这篇短文根本算不上什么深入的分析性的文章,所以在标题前加上了“浅谈”二字,希望对于一般的读者来说,可以给你一个相对直观些的对反射的认识。
                                                            --2005/05/23 于东莞
在这里对反射以及反射的概念在最后给出简要的解释。
一.用来测试的程序集文件的建立。
首先你需要建立一个类库文件(编译后扩展名为.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()
        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
二.测试验证的程序
建立一个winform的程序,命名假设为:testreflection
从工具栏里拖两个按钮,命名为button1,button2.
1.在程序的最上面加入引用:
Imports System
Imports System.Reflection
Imports System.Type
2.在button1的click事件里写:
        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 ‘如果是枚举
                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可见,他们都是创建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 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
    '使用反射创建实例并给属性赋值
    Private Sub testreadwriteproperties()
        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))
        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)
321 north street
", 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
            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
            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):这里的类型区分于值类型与引用类型中的类型,它包括类,枚举,值类型,接口等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值