在循环中调用泛型方法,在编译时已知不同类型的方法
本文关键字:同类型 方法 编译 循环 调用 泛型方法 | 更新日期: 2023-09-27 18:32:56
让我们考虑一个接口中的方法:
public Interface IA {
T[] Get<T>() where T : IB;
}
在另一个地方,我想对编译时已知的 n 种类型调用此方法 n 次。下面的代码说明了我的意图。
foreach(Type t in new Type[] { typeof(X), typeof(Y), typeof(Z) })
{
InterfaceXYZImplement[] arr = c.Resolve<IA>().Get<t>();
//...more here
}
现在,foreach
循环显然使类型成为运行时值,因此我必须使用MakeGenericMethod
。
有没有办法以这样一种方式编写代码,即我可以为X
、Y
和Z
执行代码,但调用只编写一次的方法?
将代码包装在方法中只会将问题向上移动(这是一个部分解决方案,但不是最终的解决方案,呵呵(。
您可以使用
一些帮助程序方法来实现此目的,该方法会做出很多假设并使用 中的新 dynamic
关键字。NET4.
基本上,当使用该类型的参数是dynamic
时,该解决方案利用DLR的功能来正确推断要用于泛型方法的类型。为此,您需要两个帮助程序方法:
IB[] Get(IA a, Type t)
{
dynamic dummy = Activator.CreateInstance(t);
return Get(a, dummy);
}
T[] Get<T>(IA a, T dummy) where T : IB
{
return a.Get<T>();
}
您的代码将调用这些帮助程序方法中的第一个:
foreach(var t in new Type[] { typeof(X), typeof(Y), typeof(Z) })
{
IB[] arr = Get(c.Resolve<IA>(), t);
// do more stuff here
}
如您所见,这种方法有几个缺点:
- 对于循环中的每个类型,通过
Activator.CreateInstance(t)
创建一个新实例。此行假设存在可以使用的公共无参数构造函数,并且此构造函数不执行任何繁重的操作。 - 如果循环中的任何类型未实现
IB
则此代码将在运行时引发异常。不会有编译错误。 - 结果始终是
IB
实例的数组,而不是特定类型的数组。
定义扩展方法:
public static class Extensions
{
public static void Get<T>(this IA a, Action<T[]> action, params Type[] types) where T : IB
{
foreach (var type in types)
{
var method = a.GetType().GetMethod("Get").MakeGenericMethod(type);
var ts = (T[])method.Invoke(a, null);
action(ts);
}
}
}
用:
a.Get(arr => {
// work on result
}, typeof(X), typeof(Y), typeof(Z));