C#与CLR学习笔记(8)—— 通过反射调用泛型方法

1 调用非泛型方法

通过反射创建一个对象,然后调用其方法的一般过程为:

  1. 加载程序集,并获取类型
  2. 通过类型,实例化一个类型对象(调用静态方法则不必实例化)
  3. 根据名称、方法签名、可访问性等约束,获取要调用的方法
  4. 通过 Invoke 方法,传入实际参数,进行调用。

案例:

public class ReflectionTest
{
    // 无参构造函数
    public ReflectionTest(){}
    
    public void Show(string name, int id)
    {
        Console.WriteLine("调用了Show(string, int)");
    }
    // 私有方法
    private void Show2()
    {
        Console.WriteLine("调用了私有Show2()");
    }
}
//下面通过反射调用方法
var assembly = Assembly.Load("XX");//XX是ReflectionTest所在的程序集名称
var type = assembly.GetType("XX.ReflectionTest");
object oReflTest = Activator.CreateInstance(type);//会调用(无参)构造函数
MethodInfo mi = type.GetMethod("Show", new Type[] { typeof(string), typeof(int) });
mi.Invoke(oReflTest, new object[] { "123", 123 });
//调用私有方法
MethodInfo mi = type.GetMethod("Show2", BindingFlags.NonPublic|BindingFlags.Instance);
mi.Invoke(oReflTest, null);

2 调用泛型类的泛型方法

对于泛型类的泛型方法,过程与非泛型类的非泛型方法是一样的,只不过,泛型类的实例化方式不太一样,泛型方法的调用也不太一样。

由于未指定泛型类型实参(T)的泛型类型是一种 开放类型,开放类型是不允许进行实例化的,因此,需首先指定 T 的类型实参(例如 int, string 等实际类型),将其转为 封闭类型 后才能进行实例化。泛型方法也是类似,需指定类型实参才能传递匹配的实际参数,进行调用。
案例:

public class GenericClass<T>
{
    public void Show<W, X>(T t, W w, X x)
    {
        Console.WriteLine($"t.type={t.GetType().Name},w.type={w.GetType().Name},x.type=x.GetType().Name}");
    }
}
//通过反射调用
assembly = Assembly.Load("XX");//XX是GenericClass所在的程序集名称
Type typeOpen = assembly.GetType("XX.GenericClass`1");//注意泛型类型名称
//通过MakeGenericType()方法创建泛型类型
Type typeClosed = typeOpen.MakeGenericType(new Type[] { typeof(int) });
object oGenRefl = Activator.CreateInstance(typeClosed);

MethodInfo mi = typeClosed.GetMethod("Show");//没有重载时可以不指定方法参数类型
MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
mi2.Invoke(oGenRefl, new object[] { 12, "12", DateTime.Now });//注意泛型类型的匹配
//输出结果如下:
t.type=Int32,w.type=String,x.type=DateTime

你可能感兴趣的:(.NET,C#)