5

让我们考虑一个接口中的方法:

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,但只调用一次编写的方法?

将代码包装在方法中只会将问题向上移动(这是部分解决方案,但不是最终解决方案,呵呵)。

4

2 回答 2

3

您可以使用一些辅助方法来实现这一点,该方法做了很多假设并使用dynamic.NET4 中的 new 关键字。

基本上,当使用该类型的参数是dynamic. 为此,您将需要两个辅助方法:

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
}

如您所见,这种方法有几个缺点:

  1. 对于循环中的每种类型,都会通过Activator.CreateInstance(t). 这一行假设存在一个可以使用的公共无参数构造函数,并且这个构造函数没有做任何繁重的事情。
  2. 如果循环中的任何类型未实现IB此代码将在运行时抛出异常。不会有编译错误。
  3. 结果始终是IB实例数组,而不是特定类型的数组。
于 2012-05-03T09:59:31.197 回答
3

定义一个扩展方法:

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));
于 2012-05-03T10:10:42.003 回答