反射调用方法

首先准备一个要操作的类,有以下几个方法

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);

posted @ 2020-04-18 22:44  旗木卡卡罗特  阅读(1084)  评论(0编辑  收藏  举报