版本:.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); } }