通过Type.InvokeMethod实现方法的重载

版本:.NET Framework 3.5

先来一个反射调用方法的例子:

using System;
using System.Reflection;

class Example
{
    static void Main()
    {
        Type t = typeof(String);

        MethodInfo substr = t.GetMethod("Substring", 
            new Type[] { typeof(int), typeof(int) });
		// 用MethodBase类的Invoke(object obj, object[] parameters)方法
        Object result = 
            substr.Invoke("Hello, World!", new Object[] { 7, 5 });// 射调用String的Substring(int startIndex, int length)方法
        Console.WriteLine("{0} returned \"{1}\".", substr, result);
    }
}

/* 输出:
System.String Substring(Int32, Int32) returned "World".
 */

进入正题:通过Type.InvokeMethod实现方法的重载

 1)介绍type

 Type 为 System.Reflection 功能的根,也是访问元数据的主要方式。使用 Type 的成员获取关于类型声明的信息,如构造函数、方法、字段、属性和类的事件,以及在其中部署该类的模块和程序集。
在多线程方案中,不要锁定 Type 对象以同步对 static 数据的访问。其他不受您控制的代码可能也会锁定您的类类型。这可能会导致死锁。应转而通过锁定私有 static 对象来同步对静态数据的访问。
这个类是线程安全的;多个线程可以同时从此类型的一个实例读取数据。Type 的实例可表示以下任何类型:

值类型
数组
接口
指针
枚举
构造泛型类型和泛型类型定义
构造泛型类型、泛型类型定义和泛型方法定义的类型实参和类型形参


 2)实例

Assembly assembly = Assembly.LoadFrom(sDllName);
Type fType = assembly.GetType(sClassName);
object instance = Activator.CreateInstance (fType);
fType.InvokeMember("classmethod",BindingFlags.InvokeMethod,null,instance,sParams);//调用指定实例instance的classmethod方法,sParams为传入参数,数量不固定,达到方法的重载

3)扩展

枚举类BindingFlags各属性含义


Default 不指定绑定标志。
IgnoreCase 指定当绑定时不应考虑成员名的大小写。
DeclaredOnly 指定只应考虑在所提供类型的层次结构级别上声明的成员。不考虑继承成员。
Instance 指定实例成员将包括在搜索中。
Static 指定静态成员将包括在搜索中。
Public 指定公共成员将包括在搜索中。
NonPublic 指定非公共成员将包括在搜索中。
FlattenHierarchy 指定应返回层次结构上的公共静态成员和受保护的静态成员。不返回继承类中的私有静态成员。静态成员包括字段、方法、事件和属性。不返回嵌套类型。
InvokeMethod 指定要调用一个方法。它不能是构造函数或类型初始值设定项。
CreateInstance 指定“反射”应该创建指定类型的实例。调用与给定参数匹配的构造函数。忽略提供的成员名。如果未指定查找类型,将应用 (Instance |Public)。调用类型初始值设定项是不可能的。
GetField 指定应返回指定字段的值。
SetField 指定应设置指定字段的值。
GetProperty 指定应返回指定属性的值。
SetProperty 指定应设置指定属性的值。对于 COM 属性,指定此绑定标志与指定 PutDispProperty 和 PutRefDispProperty 是等效的。
PutDispProperty 指定应调用 COM 对象的 PROPPUT 成员。PROPPUT 指定使用值的属性设置函数。如果属性同时具有 PROPPUT 和 PROPPUTREF,而且需要区分调用哪一个,请使用 PutDispProperty。
PutRefDispProperty 指定应调用 COM 对象的 PROPPUTREF 成员。PROPPUTREF 指定使用引用而不是值的属性设置函数。如果属性同时具有 PROPPUT 和 PROPPUTREF,而且需要区分调用哪一个,请使用 PutRefDispProperty。
ExactBinding 指定提供参数的类型必须与对应形参的类型完全匹配。如果调用方提供一个非空 Binder 对象,则“反射”将引发异常,因为这意味着调用方正在提供的 BindToXXX 实现将选取适当的方法。
SuppressChangeType 未实现。
OptionalParamBinding 返回其参数计数与提供参数的数目匹配的成员集。此绑定标志用于所带参数具有默认值的方法和带变量参数 (varargs) 的方法。此标志应只与 Type.InvokeMember 一起使用。
IgnoreReturn 在 COM interop 中用于指定可以忽略成员的返回值。

举例

using System;
using System.Reflection;
using System.IO;

namespace BindingFlagsSnippet
{
    class EntryPoint
    {
        static void Main(string[] args)
        {
            Invoke.Go();
        }
    }


    class Invoke
    {
        public static void Go()
        {
            // BindingFlags.InvokeMethod
            // Call a static method.
            Type t = typeof (TestClass);

            Console.WriteLine();
            Console.WriteLine("Invoking a static method.");
            Console.WriteLine("-------------------------");
            t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object [] {});

            // BindingFlags.InvokeMethod
            // Call an instance method.
            TestClass c = new TestClass ();
            Console.WriteLine();
            Console.WriteLine("Invoking an instance method.");
            Console.WriteLine("----------------------------");
            c.GetType().InvokeMember ("AddUp", BindingFlags.InvokeMethod, null, c, new object [] {});
            c.GetType().InvokeMember ("AddUp", BindingFlags.InvokeMethod, null, c, new object [] {});

            // BindingFlags.InvokeMethod
            // Call a method with parameters.
            object [] args = new object [] {100.09, 184.45};
            object result;
            Console.WriteLine();
            Console.WriteLine("Invoking a method with parameters.");
            Console.WriteLine("---------------------------------");
            result = t.InvokeMember ("ComputeSum", BindingFlags.InvokeMethod, null, null, args);
            Console.WriteLine ("{0} + {1} = {2}", args[0], args[1], result);

            // BindingFlags.GetField, SetField
            Console.WriteLine();
            Console.WriteLine("Invoking a field (getting and setting.)");
            Console.WriteLine("--------------------------------------");
            // Get a field value.
            result = t.InvokeMember ("Name", BindingFlags.GetField, null, c, new object [] {});
            Console.WriteLine ("Name == {0}", result);
            // Set a field.
            t.InvokeMember ("Name", BindingFlags.SetField, null, c, new object [] {"NewName"});
            result = t.InvokeMember ("Name", BindingFlags.GetField, null, c, new object [] {});
            Console.WriteLine ("Name == {0}", result);

            Console.WriteLine();
            Console.WriteLine("Invoking an indexed property (getting and setting.)");
            Console.WriteLine("--------------------------------------------------");
            // BindingFlags.GetProperty
            // Get an indexed property value.
            int  index = 3;
            result = t.InvokeMember ("Item", BindingFlags.GetProperty, null, c, new object [] {index});
            Console.WriteLine ("Item[{0}] == {1}", index, result);
            // BindingFlags.SetProperty
            // Set an indexed property value.
            index = 3;
            t.InvokeMember ("Item", BindingFlags.SetProperty, null, c, new object [] {index, "NewValue"});
            result = t.InvokeMember ("Item", BindingFlags.GetProperty , null, c, new object [] {index});
            Console.WriteLine ("Item[{0}] == {1}", index, result);

            Console.WriteLine();
            Console.WriteLine("Getting a field or property.");
            Console.WriteLine("----------------------------");
            // BindingFlags.GetField
            // Get a field or property.
            result = t.InvokeMember ("Name", BindingFlags.GetField | BindingFlags.GetProperty, null, c, new object [] {});
            Console.WriteLine ("Name == {0}", result);
            // BindingFlags.GetProperty
            result = t.InvokeMember ("Value", BindingFlags.GetField | BindingFlags.GetProperty, null, c, new object [] {});
            Console.WriteLine ("Value == {0}", result);

            Console.WriteLine();
            Console.WriteLine("Invoking a method with named parameters.");
            Console.WriteLine("---------------------------------------");
            // BindingFlags.InvokeMethod
            // Call a method using named parameters.
            object[] argValues = new object [] {"Mouse", "Micky"};
            String [] argNames = new String [] {"lastName", "firstName"};
            t.InvokeMember ("PrintName", BindingFlags.InvokeMethod, null, null, argValues, null, null, argNames);

            Console.WriteLine();
            Console.WriteLine("Invoking a default member of a type.");
            Console.WriteLine("------------------------------------");
            // BindingFlags.Default
            // Call the default member of a type.
            Type t3 = typeof (TestClass2);
            t3.InvokeMember ("", BindingFlags.InvokeMethod | BindingFlags.Default, null, new TestClass2(), new object [] {});

            // BindingFlags.Static, NonPublic, and Public
            // Invoking a member by reference.
            Console.WriteLine();
            Console.WriteLine("Invoking a method by reference.");
            Console.WriteLine("-------------------------------");
            MethodInfo m = t.GetMethod("Swap");
            args = new object[2];
            args[0] = 1;
            args[1] = 2;
            m.Invoke(new TestClass(),args);
            Console.WriteLine ("{0}, {1}", args[0], args[1]);
            // The string is case-sensitive.
            Type type = Type.GetType("System.String");

            // Check to see if the value is valid. If the object is null, the type does not exist.
            if (type == null)
            {
                Console.WriteLine("Please ensure that you specify only valid types in the type field.");
                Console.WriteLine("The type name is case-sensitive.");
                return;
            }
            // Declare and populate the arrays to hold the information.
            // You must declare either NonPublic or Public with Static or the search will not work.
            FieldInfo [] fi = type.GetFields (BindingFlags.Static |
                BindingFlags.NonPublic | BindingFlags.Public);
            // BindingFlags.NonPublic
            MethodInfo [] miNonPublic = type.GetMethods (BindingFlags.Static |
                BindingFlags.NonPublic);
            // BindingFlags.Public
            MethodInfo [] miPublic = type.GetMethods (BindingFlags.Static |
                BindingFlags.Public);

            // Iterate through all the nonpublic methods.
            foreach (MethodInfo method in miNonPublic)
            {
                Console.WriteLine(method);
            }
            // Iterate through all the public methods.
            foreach (MethodInfo method in miPublic)
            {
                Console.WriteLine(method);
            }
            // Iterate through all the fields.
            foreach (FieldInfo f in fi)
            {
                Console.WriteLine(f);
            }

            // BindingFlags.Instance
            // Call an instance method.
            TestClass tc = new TestClass ();
            Console.WriteLine();
            Console.WriteLine("Invoking an Instance method.");
            Console.WriteLine("----------------------------");
            tc.GetType().InvokeMember ("AddUp", BindingFlags.Public |
                BindingFlags.Instance | BindingFlags.CreateInstance,
                null, tc, new object [] {});

            // BindingFlags.CreateInstance
            // Calling and creating an instance method.
            Console.WriteLine();
            Console.WriteLine("Invoking and creating an instance method.");
            Console.WriteLine("-----------------------------------------");
            tc.GetType().InvokeMember ("AddUp", BindingFlags.Public |
                BindingFlags.Instance | BindingFlags.CreateInstance,
                null, tc, new object [] {});

            // BindingFlags.DeclaredOnly
            TestClass tc2 = new TestClass();
            Console.WriteLine();
            Console.WriteLine("DeclaredOnly members");
            Console.WriteLine("---------------------------------");
            System.Reflection.MemberInfo[] memInfo =
                tc2.GetType().GetMembers(BindingFlags.DeclaredOnly);
            for(int i=0;i<memInfo.Length;i++)
            {
                Console.WriteLine(memInfo[i].Name);
            }

            // BindingFlags.SuppressChangeType
            TestClass obj = new TestClass();
            Console.WriteLine();
            Console.WriteLine("Invoking static method - PrintName");
            Console.WriteLine("---------------------------------");
            System.Reflection.MethodInfo methInfo =
                obj.GetType().GetMethod("PrintName");
            methInfo.Invoke(obj,BindingFlags.SuppressChangeType |
                BindingFlags.InvokeMethod, null,new object[]
                {"Brad","Smith"},null);

            // BindingFlags.IgnoreCase
            Console.WriteLine();
            Console.WriteLine("Using IgnoreCase and invoking the PrintName method.");
            Console.WriteLine("---------------------------------------------------");
            methInfo = obj.GetType().GetMethod("PrintName");
            methInfo.Invoke(obj,BindingFlags.IgnoreCase |
                BindingFlags.InvokeMethod, null,new object[]
                {"brad","smith"},null);

            // BindingFlags.IgnoreReturn
            Console.WriteLine();
            Console.WriteLine("Using IgnoreReturn and invoking the PrintName method.");
            Console.WriteLine("-----------------------------------------------------");
            methInfo = obj.GetType().GetMethod("PrintName");
            methInfo.Invoke(obj,BindingFlags.IgnoreReturn |
                BindingFlags.InvokeMethod, null,new object[]
                {"Brad","Smith"},null);

            // BindingFlags.OptionalParamBinding
            Console.WriteLine();
            Console.WriteLine("Using OptionalParamBinding and invoking the PrintName method.");
            Console.WriteLine("-------------------------------------------------------------");
            methInfo = obj.GetType().GetMethod("PrintName");
            methInfo.Invoke(obj,BindingFlags.OptionalParamBinding |
                BindingFlags.InvokeMethod, null,new object[]
                {"Brad","Smith"},null);

            // BindingFlags.ExactBinding
            Console.WriteLine();
            Console.WriteLine("Using ExactBinding and invoking the PrintName method.");
            Console.WriteLine("-----------------------------------------------------");
            methInfo = obj.GetType().GetMethod("PrintName");
            methInfo.Invoke(obj,BindingFlags.ExactBinding |
                BindingFlags.InvokeMethod, null,new object[]
                {"Brad","Smith"},null);

            // BindingFlags.FlattenHierarchy
            Console.WriteLine();
            Console.WriteLine("Using FlattenHierarchy and invoking the PrintName method.");
            Console.WriteLine("---------------------------------------------------------");
            methInfo = obj.GetType().GetMethod("PrintName");
            methInfo.Invoke(obj,BindingFlags.FlattenHierarchy |
                BindingFlags.InvokeMethod, null,new object[]
                {"Brad","Smith"},null);
        }
    }




### 回答1: whitebox.invokemethod是一个Java测试工具中的方法,用于调用私有方法和属性。它可以通过反射机制来访问和执行类中的私有方法和属性,以便进行单元测试和调试。使用whitebox.invokemethod可以避免修改源代码来测试私有方法和属性的问题。 ### 回答2: whitebox.invokemethod是一个Java代码中的方法,用于通过反射机制调用一个指定的方法。 在Java中,反射是一种机制,允许程序在运行时动态地获取和操作类、方法、属性等对象。通过反射,我们可以通过类的全限定名来获取这个类的相关信息,并且可以在运行时创建对象、调用类中的方法和获取/设置其属性。 而whitebox.invokemethod是Java中的一个工具类或者库,它封装了反射的调用方法实现,使得我们可以更加便捷地进行反射操作。 使用whitebox.invokemethod,我们可以通过传入一个类的实例,指定方法名和参数类型及参数值,来调用这个方法。它可以解决一些特殊情况下的调用问题,比如调用私有方法、访问私有属性、调用父类方法等。 whitebox.invokemethod的使用方式类似于以下示例: ``` // 假设有一个类A,其中有一个私有方法privateMethod(),我们想要调用这个方法 A instance = new A(); Whitebox.invokeMethod(instance, "privateMethod", null, null); ``` 在上述示例中,我们创建了类A的实例,并且使用whitebox.invokemethod来调用类A的私有方法privateMethod。这里的参数"privateMethod"表示方法名,第三个参数null表示参数类型(如果方法有参数的话),第四个参数null表示方法的参数值。 通过whitebox.invokemethod,我们可以实现更加灵活的动态调用方法的功能,提高了代码的灵活性和可扩展性。但是,需要注意的是,在使用反射时需要谨慎,因为反射会降低性能,并且可能违反面向对象的设计原则。 ### 回答3: whitebox.invokemethod 是一个可以在白盒测试中使用的方法。白盒测试是一种软件测试方法,其主要目的是对被测试的软件内部结构和实现细节进行测试。与黑盒测试不同,白盒测试需要测试人员具备对软件的内部工作原理有一定的了解。 whitebox.invokemethod 方法的作用是调用被测试软件内部的某个方法。通过直接调用内部方法,测试人员可以验证方法的正确性以及它们在特定场景下的表现。这可以帮助测试人员发现软件中隐藏的缺陷和潜在问题。 使用 whitebox.invokemethod 方法进行测试时,需要传入被测试方法的名称和相关参数。通过调用该方法,我们可以模拟不同的测试用例,覆盖软件内部各个执行路径,从而提高测试覆盖率。 通过应用 whitebox.invokemethod 方法,测试人员可以主动去调用软件中特定的方法,以评估其对整个系统的影响。这对于发现潜在的错误和性能问题非常有帮助。同时,whitebox.invokemethod 方法也可以用于调试目的,通过调用内部方法可以定位到软件的具体问题所在。 总而言之,whitebox.invokemethod 是一个用于白盒测试的重要工具,它允许测试人员主动调用被测试软件内部的方法,并评估其在不同场景下的表现。通过使用这个方法,可以提高测试覆盖率,发现系统中的潜在问题,并加快漏洞修复和软件优化的速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值