C# 使用反射动态调用泛型方法

解决的问题

假设我们有以下的泛型方法

public T fun(){
	return obj = new T();
}

如果T有很多,那通常的方法是使用swich进行判断

var className = "string";
var obj = new object();
swich(className){
	case "string":
		obj =fun();
		break;
	case "int":
		obj =fun();
		break;
		...
}

解决方案

上面的写法会导致大量的冗余代码。
我们想要如下的解决方案,通过传入类的名字来动态的调用fun函数

//错误的方案
public object ExcuteMethod(string className){
	var type = typeof(className);
	return fun();
}

泛型中的T是类型,而这里使用的type是参数。没有找到办法把类型当作参数传递。但是可以换一种思路,通过反射来直接执行函数。
以下是通过放射实现动态执行泛型函数


//获取当前程序集
Assembly mockAssembly = Assembly.GetExecutingAssembly();
//可以使用LoadFrom(URL)方法加载其他程序集(.dll文件),url是绝对路劲
Assembly mockAssembly = Assembly.LoadFrom("C:/test/test.dll");

//通过类名获取类,参数是类的全名,命名空间+类名,Myclass是泛型方法中fun()中的T
var curType = mockAssembly.GetType("Myspacename.Myclass");

//获取方法所在类的Type,MethodClass是存放fun()方法的类
var MethodType = typeof(MethodClass);
//如果是泛型类,如 MyGenericClass{},要这样获得Type
var MethodType = typeof(MyGenericClass<>);

//获取泛型方法,
var GenericMethod =MethodType.GetMethod(MethodName);

//如果方法是多态的,即有多个同名方法,可以通过传入Type[]参数来找到方法
//这样可以找到方法fun(string para1,int para2)
var GenericMethod =MethodType.GetMethod(
MethodName, new Type[] {typeof(string),typeof(int)});

//合并生成最终的函数
MethodInfo curMethod =GenericMethod.MakeGenericMethod(curType);

//执行函数
//如果要执行的是静态函数,则第一个参数为null
//第二个参数为参数值
//即要调用的函数应该为 static fun(string para1,int para2)
curMethod.Invoke(null, new object[]{"第一个参数的值",1});

//如果是非静态参数,第一个参数得传MethodClass的实例化对象
//即要调用的函数应该为 fun(string para1,int para2)
var classobj = new MethodClass();
curMethod.Invoke(classobj, new object[]{"第一个参数的值",1});

使用缓存存储生成的方法

利用放射生成方法非常的耗费时间,所以可以考虑将生成的方法存在缓存中,以后直接执行就行,不用每次都重新生成方法

尝试封装(失败)

尝试封装成一个函数

public object ExcuteGenericMethod(string TclassName,object[] paras);

但是遇到一个问题,如果是泛型类

MyGenericClass

//这样使用的错误的
ExcuteGenericMethod>("MySpacename.MyClass",new object[] {"test1"});

//这样使用也是错误的
fun(){
Type objType = typeof(T<>);
}

你可能感兴趣的:(随笔)