假设我们有以下的泛型方法
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<>);
}