反射调用方法
首先准备一个要操作的类,有以下几个方法
public class Test { public void Show() { Console.WriteLine("hello"); } public void Show(string name) { Console.WriteLine($"hello {name}"); } public void ShowGeneric<T>() { Console.WriteLine($"ShowGeneric,T:{typeof(T)}"); } public void ShowGeneric2<T>() { Console.WriteLine($"ShowGeneric2,T:{typeof(T)}"); } public void ShowGeneric2<T>(string name) { Console.WriteLine($"ShowGeneric2 hello {name},T:{typeof(T)}"); } public void ShowGeneric2<T>(string name,T t) { Console.WriteLine($"ShowGeneric2 hello {name},T:{t.GetType()}"); } public void ShowGeneric2<T, K>(int a) { Console.WriteLine($"T:{typeof(T)},K:{typeof(K)},a:{a}"); } }
首先获取该类的Type,创建一个实例,相当于 Test t=New T();
Type type = typeof(Test); Object obj = Activator.CreateInstance(type);
之后通过GetMethod方法获取要调用的方,第一个参数是方法名,第二个参数是方法的参数列表的Type数组。一般情况下可以省略,在这个例子中Show方法有重载,所以要加上第二个参数以指定调用哪个方法。就算没有参数也要写new Type[] { }。最后通过Invoke调用方法,第一个参数是第一步创建的实例,第二个参数是方法的参数,是Object数组,没有则为null。
MethodInfo m = type.GetMethod("Show", new Type[] { }); m.Invoke(obj, null);
下面是一个带参数的方法
MethodInfo m = type.GetMethod("Show", new Type[] { typeof(string) }); m.Invoke(obj, new object[] { "jack" });
接下来是泛型方法,MakeGenericMethod(typeof(string))指定了泛型的类型相当于t.ShowGeneric<String>()
MethodInfo m = type.GetMethod("ShowGeneric"); MethodInfo m2 = m.MakeGenericMethod(typeof(string)); m2.Invoke(obj, null);
然后是重载泛型方法的调用,对于参数列表里不包含泛型参数的方法的调用跟普通的方法是一样,而如果其中有泛型的参数的话就要用另一种方法了。
MethodInfo m = type.GetMethod("ShowGeneric2",new Type[] { }); MethodInfo m2 = m.MakeGenericMethod(typeof(string)); m2.Invoke(obj, null); MethodInfo m2 = type.GetMethod("ShowGeneric2", new Type[] {typeof(string) }); MethodInfo m3 = m2.MakeGenericMethod(typeof(string)); m3.Invoke(obj, new object[] { "jack" });
下面是一个参数列表中包含泛型类型的方法的调用,首先获取Test类中所有的方法,然后根据方法名,方法的泛型,方法的参数列表这些条件来获取到要调用的方法。
MethodInfo m = type.GetMethods().FirstOrDefault(t => { var a = t.GetGenericArguments();//获取方法的泛型参数,返回类型是Type[] var p = t.GetParameters();//获取方法的参数列表,返回类型是ParameterInfo[] return t.Name == "ShowGeneric2" && a.Length == 1 && p.Length == 2 && p[0].ParameterType == typeof(string) && p[1].ParameterType == a[0]; }); MethodInfo m2 = m.MakeGenericMethod(typeof(string)); m2.Invoke(obj, new object[] { "jack","jack" });
除此之外还有一个方法可以获取方法,就是直接将方法ToString()后比对,这种方法有个小问题是参数列表的类型,string会变成 System.String,而Int会变成Int32,一会有Sytem一会没有,搞不懂是根据什么来的。用这种方法最好先看下输出一个结果再写判断条件。
MethodInfo m = type.GetMethod("Show", new Type[] { });m.Invoke(obj, null);