zoukankan      html  css  js  c++  java
  • 反射动态加载和使用类型

      1反射提供语言编译器(如 Microsoft Visual Basic 2005 和 JScript)用于实现隐式后期绑定的基础结构。绑定是查找与唯一指定的类型相对应的声明(即实现)的过程。如果此过程是在运行时而不是在编译时发生,则称其为“后期绑定”。利用 Visual Basic 2005,可以在代码中使用隐式后期绑定;Visual Basic 编译器会调用一个帮助器方法,该方法使用反射来获取对象类型。传递给帮助器方法的参数有助于在运行时调用正确的方法。这些参数包括:对其调用方法的实例(对象),被调用方法的名称(字符串),以及传递给被调用方法的参数(对象数组)。
      2
      3在下面的示例中,Visual Basic 编译器使用反射隐式地对其类型在编译时未知的对象调用方法。HelloWorld 类具有一个 PrintHello 方法,它输出与传递给 PrintHello 方法的某些文本串联的“Hello World”。在此示例中调用的 PrintHello 方法实际上是 Type..::.InvokeMember;Visual Basic 代码允许按照对象 (helloObj) 的类型在编译时已知(早期绑定)而不是在运行时已知(后期绑定)的方式来调用 PrintHello 方法。
      4
      5  复制代码 
      6Imports System
      7Module Hello
      8    Sub Main()
      9        ' Sets up the variable.
     10        Dim helloObj As Object
     11        ' Creates the object.
     12        helloObj = new HelloWorld()
     13        ' Invokes the print method as if it was early bound
     14        ' even though it is really late bound.
     15        helloObj.PrintHello("Visual Basic Late Bound")
     16    End Sub
     17End Module
     18 
     19
     20自定义绑定
     21除了由编译器隐式地用来进行后期绑定之外,反射还可以在代码中显式地用来完成后期绑定。
     22
     23公共语言运行库支持多种编程语言,但这些语言的绑定规则各不相同。在早期绑定的情况下,代码生成器可以完全控制此绑定。但是,当通过反射进行后期绑定时,必须用自定义绑定来控制绑定。Binder 类提供了对成员选择和调用的自定义控制。
     24
     25利用自定义绑定,您可以在运行时加载程序集,获取有关该程序集中类型的信息,然后对该类型调用方法或访问该类型的字段或属性。如果您在编译时(例如当对象类型依赖于用户输入时)不知道对象的类型,就可以使用这种方法。
     26
     27下面的示例说明不提供参数类型转换的简单的自定义联编程序。Simple_Type.dll 的代码位于示例主体之前。确保生成 Simple_Type.dll,然后在生成时在项目中包括对它的引用。
     28
     29Visual Basic  复制代码 
     30' Code for building Simple_Type.dll.
     31Imports System
     32
     33Namespace Simple_Type
     34    Public Class MySimpleClass
     35        Public Overloads Sub MyMethod(ByVal str As String, 
     36            ByVal i As Integer)
     37            Console.WriteLine("MyMethod parameters: {0}, {1}", str, i)
     38        End Sub 'MyMethod
     39
     40        Public Overloads Sub MyMethod(ByVal str As String, 
     41            ByVal i As Integer, ByVal j As Integer)
     42            Console.WriteLine("MyMethod parameters: {0}, {1}, {2}", str, 
     43                i, j)
     44        End Sub 'MyMethod
     45    End Class 'MySimpleClass
     46End Namespace 'Simple_Type
     47
     48Imports System
     49Imports System.Reflection
     50Imports System.Globalization
     51Imports Simple_Type.Simple_Type
     52
     53Namespace Custom_Binder
     54    Class MyMainClass
     55        Shared Sub Main()
     56            ' Get the type of MySimpleClass.
     57            Dim myType As Type = GetType(MySimpleClass)
     58            ' Get an instance of MySimpleClass.
     59            Dim myInstance As New MySimpleClass()
     60            Dim myCustomBinder As New MyCustomBinder()
     61            ' Get the method information for the overload being sought.
     62            Dim myMethod As MethodInfo = myType.GetMethod("MyMethod"
     63                BindingFlags.Public Or BindingFlags.Instance, 
     64                    myCustomBinder, New Type() {GetType(String), 
     65                        GetType(Integer)}
    , Nothing)
     66            Console.WriteLine(myMethod.ToString())
     67            ' Invoke the overload.
     68            myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, 
     69                myCustomBinder, myInstance, 
     70                    New [Object]() {"Testing", CInt(32)})
     71        End Sub 'Main
     72    End Class 'MyMainClass
     73
     74    '****************************************************
     75    ' A simple custom binder that provides no
     76    ' argument type conversion.
     77    '****************************************************
     78    Class MyCustomBinder
     79        Inherits Binder
     80
     81        Public Overrides Function BindToMethod(ByVal bindingAttr As 
     82            BindingFlags, ByVal match() As MethodBase, ByRef args() As 
     83                Object, ByVal modifiers() As ParameterModifier, ByVal 
     84                    culture As CultureInfo, ByVal names() As String, ByRef 
     85                        state As Object) As MethodBase
     86            If match Is Nothing Then
     87                Throw New ArgumentNullException("match")
     88            End If
     89            ' Arguments are not being reordered.
     90            state = Nothing
     91            ' Find a parameter match and return the first method with
     92            ' parameters that match the request.
     93            Dim mb As MethodBase
     94            For Each mb In match
     95                Dim parameters As ParameterInfo() = mb.GetParameters()
     96                If ParametersMatch(parameters, args) Then
     97                    Return mb
     98                End If
     99            Next mb
    100            Return Nothing
    101        End Function 'BindToMethod
    102
    103        Public Overrides Function BindToField(ByVal bindingAttr As 
    104            BindingFlags, ByVal match() As FieldInfo, ByVal value As 
    105                Object, ByVal culture As CultureInfo) As FieldInfo
    106            If match Is Nothing Then
    107                Throw New ArgumentNullException("match")
    108            End If
    109            Dim fi As FieldInfo
    110            For Each fi In match
    111                If fi.GetType() Is value.GetType() Then
    112                    Return fi
    113                End If
    114            Next fi
    115            Return Nothing
    116        End Function 'BindToField
    117
    118        Public Overrides Function SelectMethod(ByVal bindingAttr As 
    119            BindingFlags, ByVal match() As MethodBase, ByVal types() As 
    120                Type, ByVal modifiers() As ParameterModifier) As 
    121                    MethodBase
    122            If match Is Nothing Then
    123                Throw New ArgumentNullException("match")
    124            End If
    125            ' Find a parameter match and return the first method with
    126            ' parameters that match the request.
    127            Dim mb As MethodBase
    128            For Each mb In match
    129                Dim parameters As ParameterInfo() = mb.GetParameters()
    130                If ParametersMatch(parameters, types) Then
    131                    Return mb
    132                End If
    133            Next mb
    134            Return Nothing
    135        End Function 'SelectMethod
    136
    137        Public Overrides Function SelectProperty(ByVal bindingAttr As 
    138            BindingFlags, ByVal match() As PropertyInfo, ByVal returnType 
    139                As Type, ByVal indexes() As Type, ByVal modifiers() As 
    140                    ParameterModifier) As PropertyInfo
    141            If match Is Nothing Then
    142                Throw New ArgumentNullException("match")
    143            End If
    144            Dim pi As PropertyInfo
    145            For Each pi In match
    146                If pi.GetType() Is returnType And 
    147                    ParametersMatch(pi.GetIndexParameters(), indexes) Then
    148                    Return pi
    149                End If
    150            Next pi
    151            Return Nothing
    152        End Function 'SelectProperty
    153
    154        Public Overrides Function ChangeType(ByVal value As Object, 
    155            ByVal myChangeType As Type, ByVal culture As CultureInfo) 
    156                As Object
    157            Try
    158                Dim newType As Object
    159                newType = Convert.ChangeType(value, myChangeType)
    160
    161                Return newType
    162                ' Throw an InvalidCastException if the conversion cannot
    163                ' be done by the Convert.ChangeType method.
    164            Catch
    165            End Try
    166        End Function 'ChangeType
    167
    168        Public Overrides Sub ReorderArgumentArray(ByRef args() As Object, 
    169            ByVal state As Object)
    170            ' No operation is needed here because BindToMethod does not
    171            ' reorder the args array. The most common implementation
    172            ' of this method is shown below.
    173            
    174            ' ((BinderState)state).args.CopyTo(args, 0);
    175        End Sub 'ReorderArgumentArray
    176
    177        ' Returns true only if the type of each object in a matches
    178        ' the type of each corresponding object in b.
    179        Private Overloads Function ParametersMatch(ByVal a() As 
    180            ParameterInfo, ByVal b() As Object) As Boolean
    181            If a.Length <> b.Length Then
    182                Return False
    183            End If
    184            Dim i As Integer
    185            For i = 0 To a.Length - 1
    186                If Not (a(i).ParameterType Is b(i).GetType()) Then
    187                    Return False
    188                End If
    189            Next i
    190            Return True
    191        End Function 'ParametersMatch
    192
    193        ' Returns true only if the type of each object in a matches
    194        ' the type of each corresponding entry in b.
    195        Private Overloads Function ParametersMatch(ByVal a() As 
    196            ParameterInfo, ByVal b() As Type) As Boolean
    197            If a.Length <> b.Length Then
    198                Return False
    199            End If
    200            Dim i As Integer
    201            For i = 0 To a.Length - 1
    202                If Not (a(i).ParameterType Is b(i)) Then
    203                    Return False
    204                End If
    205            Next i
    206            Return True
    207        End Function 'ParametersMatch
    208    End Class 'MyCustomBinder
    209End Namespace 'Custom_Binder
    210
    211
    212
    213 
    214C#  复制代码 
    215// Code for building SimpleType.dll.
    216using System;
    217
    218namespace Simple_Type
    219{
    220    public class MySimpleClass
    221    {
    222        public void MyMethod(string str, int i)
    223        {
    224            Console.WriteLine("MyMethod parameters: {0}, {1}", str, i);
    225        }

    226
    227        public void MyMethod(string str, int i, int j)
    228        {
    229            Console.WriteLine("MyMethod parameters: {0}, {1}, {2}"
    230                str, i, j);
    231        }

    232    }

    233}

    234
    235
    236using System;
    237using System.Reflection;
    238using System.Globalization;
    239using Simple_Type;
    240namespace Custom_Binder
    241{
    242    class MyMainClass
    243    {
    244        static void Main()
    245        {
    246            // Get the type of MySimpleClass.
    247            Type myType = typeof(MySimpleClass);
    248
    249            // Get an instance of MySimpleClass.
    250            MySimpleClass myInstance = new MySimpleClass();
    251            MyCustomBinder myCustomBinder = new MyCustomBinder();
    252
    253            // Get the method information for the particular overload 
    254            // being sought.
    255            MethodInfo myMethod = myType.GetMethod("MyMethod"
    256                BindingFlags.Public | BindingFlags.Instance,
    257                myCustomBinder, new Type[] {typeof(string), 
    258                    typeof(int)}
    null);
    259            Console.WriteLine(myMethod.ToString());
    260            
    261            // Invoke the overload.
    262            myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, 
    263                myCustomBinder, myInstance, 
    264                    new Object[] {"Testing", (int)32});
    265        }

    266    }

    267
    268    //****************************************************
    269    //  A simple custom binder that provides no
    270    //  argument type conversion.
    271    //****************************************************
    272    class MyCustomBinder : Binder
    273    {
    274        public override MethodBase BindToMethod(
    275            BindingFlags bindingAttr,
    276            MethodBase[] match,
    277            ref object[] args,
    278            ParameterModifier[] modifiers,
    279            CultureInfo culture,
    280            string[] names,
    281            out object state)
    282        {
    283            if(match == null)
    284                throw new ArgumentNullException("match");
    285            // Arguments are not being reordered.
    286            state = null;
    287            // Find a parameter match and return the first method with
    288            // parameters that match the request.
    289            foreach(MethodBase mb in match)
    290            {
    291                ParameterInfo[] parameters = mb.GetParameters();
    292
    293                if(ParametersMatch(parameters, args))
    294                    return mb;
    295            }

    296            return null;
    297        }

    298
    299        public override FieldInfo BindToField(BindingFlags bindingAttr, 
    300            FieldInfo[] match, object value, CultureInfo culture)
    301        {
    302            if(match == null)
    303                throw new ArgumentNullException("match");
    304            foreach(FieldInfo fi in match)
    305            {
    306                if(fi.GetType() == value.GetType())
    307                    return fi;
    308            }

    309            return null;
    310        }

    311
    312        public override MethodBase SelectMethod(
    313            BindingFlags bindingAttr,
    314            MethodBase[] match,
    315            Type[] types,
    316            ParameterModifier[] modifiers)
    317        {
    318            if(match == null)
    319                throw new ArgumentNullException("match");
    320
    321            // Find a parameter match and return the first method with
    322            // parameters that match the request.
    323            foreach(MethodBase mb in match)
    324            {
    325                ParameterInfo[] parameters = mb.GetParameters();
    326                if(ParametersMatch(parameters, types))
    327                    return mb;
    328            }

    329
    330            return null;
    331        }

    332
    333        public override PropertyInfo SelectProperty(
    334            BindingFlags bindingAttr,
    335            PropertyInfo[] match,
    336            Type returnType,
    337            Type[] indexes,
    338            ParameterModifier[] modifiers)
    339        {
    340            if(match == null)
    341                throw new ArgumentNullException("match");
    342            foreach(PropertyInfo pi in match)
    343            {
    344                if(pi.GetType() == returnType && 
    345                    ParametersMatch(pi.GetIndexParameters(), indexes))
    346                    return pi;
    347            }

    348            return null;
    349        }

    350
    351        public override object ChangeType(
    352            object value,
    353            Type myChangeType,
    354            CultureInfo culture)
    355        {
    356            try
    357            {
    358                object newType;
    359                newType = Convert.ChangeType(value, myChangeType);
    360                return newType;
    361            }

    362            // Throw an InvalidCastException if the conversion cannot
    363            // be done by the Convert.ChangeType method.
    364            catch(InvalidCastException)
    365            {
    366                return null;
    367            }

    368        }

    369
    370        public override void ReorderArgumentArray(ref object[] args, 
    371            object state)
    372        {
    373            // No operation is needed here because BindToMethod does not
    374            // reorder the args array. The most common implementation
    375            // of this method is shown below.
    376            
    377            // ((BinderState)state).args.CopyTo(args, 0);
    378        }

    379
    380        // Returns true only if the type of each object in a matches
    381        // the type of each corresponding object in b.
    382        private bool ParametersMatch(ParameterInfo[] a, object[] b)
    383        {
    384            if(a.Length != b.Length)
    385                return false;
    386            for(int i = 0; i < a.Length; i++)
    387            {
    388                if(a[i].ParameterType != b[i].GetType())
    389                    return false;
    390            }

    391            return true;
    392        }

    393
    394        // Returns true only if the type of each object in a matches
    395        // the type of each corresponding entry in b.
    396        private bool ParametersMatch(ParameterInfo[] a, Type[] b)
    397        {
    398            if(a.Length != b.Length)
    399                return false;
    400            for(int i = 0; i < a.Length; i++)
    401            {
    402                if(a[i].ParameterType != b[i])
    403                    return false;
    404            }

    405            return true;
    406        }

    407    }

    408}

    409 
    410
    411InvokeMember 和 CreateInstance
    412使用 Type..::.InvokeMember 可调用类型的成员。各个类(如 System.Activator 和 System.Reflection.Assembly)的 CreateInstance 方法是 InvokeMember 的特殊形式,它们可新建特定类型的实例。Binder 类用于在这些方法中进行重载决策和参数强制。
    413
    414下面的示例显示参数强制(类型转换)和成员选择的三种可能的组合。在第 1 种情况中,不需要任何参数强制或成员选择。在第 2 种情况中,只需要成员选择。在第 3 种情况中,只需要参数强制。
    415
    416C#  复制代码 
    417public class CustomBinderDriver
    418{
    419    public static void Main (string[] arguments)
    420    {
    421    Type t = typeof (CustomBinderDriver);
    422    CustomBinder binder = new CustomBinder();
    423    BindingFlags flags = BindingFlags.InvokeMethod|BindingFlags.Instance|
    424        BindingFlags.Public|BindingFlags.Static;
    425
    426    // Case 1. Neither argument coercion nor member selection is needed.
    427    args = new Object[] {};
    428    t.InvokeMember ("PrintBob", flags, binder, null, args);
    429
    430    // Case 2. Only member selection is needed.
    431    args = new Object[] {42};
    432    t.InvokeMember ("PrintValue", flags, binder, null, args);
    433
    434    // Case 3. Only argument coercion is needed.
    435    args = new Object[] {"5.5"};
    436    t.InvokeMember ("PrintNumber", flags, binder, null, args);
    437    }

    438
    439    public static void PrintBob ()
    440    {
    441        Console.WriteLine ("PrintBob");
    442    }

    443
    444    public static void PrintValue (long value)
    445    {
    446        Console.WriteLine ("PrintValue ({0})", value);
    447    }

    448    public static void PrintValue (String value)
    449    {
    450        Console.WriteLine ("PrintValue\"{0}\")", value);
    451    }

    452   
    453    public static void PrintNumber (double value)
    454    {
    455        Console.WriteLine ("PrintNumber ({0})", value);
    456    }

    457}

    458 
    459
    460当多个成员具有相同的名称时,将需要重载决策。Binder..::.BindToMethod 和 Binder..::.BindToField 方法用于解析与单个成员的绑定。Binder.BindToMethod 还通过 get 和 set 属性访问器提供了属性解析。
    461
    462BindToMethod 返回要调用的 MethodBase;如果无法进行这种调用,则返回 null 引用(在 Visual Basic 中为 Nothing)。虽然 MethodBase 返回值通常是 match 参数中所包含的值之一,但它并不必如此。
    463
    464当存在 ByRef 参数时,调用方可能需要取回这些参数。因此,如果 BindToMethod 已经操作参数数组,Binder 会允许客户端将参数数组映射回它的初始形式。为了实现这一目的,必须向调用方保证参数的顺序不会改变。当按名称传递参数时,Binder 将重新排列参数数组,这就是调用方所见的参数。有关更多信息,请参见 Binder..::.ReorderArgumentArray。
    465
    466可用成员集包括在类型和任何基类型中定义的成员。如果指定 BindingFlags.NonPublic,将返回该成员集中具有任何可访问性的成员。如果未指定 BindingFlags.NonPublic,联编程序就必须强制可访问性规则。当指定 Public 或 NonPublic 绑定标志时,还必须指定 Instance 或 Static 绑定标志,否则不会返回任何成员。
    467
    468如果只有一个成员具有给定名称,则不必进行回调,而在该方法上进行绑定。代码示例的第 1 种情况说明了这一点:只有一个 PrintBob 方法可用,因此不需要进行回调。
    469
    470如果可用集中有多个成员,所有这些方法都将传递给 BindToMethod,它将选择正确的方法并将其返回。在代码示例的第 2 种情况下,有两个名为 PrintValue 的方法。对 BindToMethod 的调用将选择正确的方法。
    471
    472ChangeType 执行参数强制转换(类型转换),以便将实参转换为选定方法的形参的类型。即使类型完全匹配,也会为每个参数调用 ChangeType。
    473
    474在代码示例的第 3 种情况下,将类型为 String 值为“5.5”的实参传递给了具有类型为 Double 的形参的方法。要使调用成功,必须将字符串值“5.5”转换为 double 值。ChangeType 会执行此转换。
    475
    476ChangeType 仅执行无损或扩大强制,如下表所示。
    477
    478源类型
    479 目标类型
    480 
    481任何类型
    482 它的基类型
    483 
    484任何类型
    485 它所实现的接口
    486 
    487Char
    488 UInt16、UInt32、Int32、UInt64、Int64、Single、Double
    489 
    490Byte
    491 Char、UInt16、Int16、UInt32、Int32、UInt64、Int64、Single、Double
    492 
    493SByte
    494 Int16、Int32、Int64、Single、Double
    495 
    496UInt16
    497 UInt32、Int32、UInt64、Int64、Single、Double
    498 
    499Int16
    500 Int32、Int64、Single、Double
    501 
    502UInt32
    503 UInt64、Int64、Single、Double
    504 
    505Int32
    506 Int64、Single、Double
    507 
    508UInt64
    509 Single、Double
    510 
    511Int64
    512 Single、Double
    513 
    514Single
    515 Double
    516 
    517非引用类型
    518 引用类型
    519 
    520
    521Type 类具有 Get 方法,这些方法使用 Binder 类型的参数来解析对特定成员的引用。Type..::.GetConstructor、Type..::.GetMethod 和 Type..::.GetProperty 通过为当前类型的特定成员提供签名信息来搜索该成员。对 Binder..::.SelectMethod 和 Binder..::.SelectProperty 进行回调以选择相应方法的给定签名信息。
    522
    这里和大家分享和学习如何学IT!
  • 相关阅读:
    spring Cloud中,解决Feign/Ribbon整合Hystrix第一次请求失败的问题?
    spring boot集成mybatis
    feign实现服务间的负载均衡
    如何解决Eureka Server不踢出已关停的节点的问题?
    spring-cloud-ribbon负载均衡
    安装配置php5.4 win2003
    ThinkPHP3.2 G函数代码及 使用方法
    php获取数组第一个值 current()
    checkbox全选,反选,取消选择 jquery
    JavaScript If...Else 语句
  • 原文地址:https://www.cnblogs.com/fuchifeng/p/1299460.html
Copyright © 2011-2022 走看看