通过使用委托参数进行反射来调用泛型方法的问题

时间:2015-10-31 21:51:25

标签: c# generics reflection delegates

我一直在搞乱这个超过一个小时,似乎无法做到这一点。这是我得到的例外之一:

  

错误:类型System.Func1[System.Object]的对象不能   转换为System.Func1[System.Collections.Generic.IEnumerable1[System.Collections.Generic.IEnumerable1[System.Object]]]类型。

基本上我有一个通用的工厂方法,看起来像这样

ReturnItem<TResult> CreateOutput<T, TResult>(Func<IEnumerable<T>> postBack,
    Processor manager) where TResult : class;

我正在尝试反思,但Func<IEnumerable<T>>给我带来了问题。这是我试图调用它的代码:

var infer = Factory.CreateReturnInference(); //Keypair value (type, type) is NOT an NormalOutputFactory in this instance
Func<object> callBack = () => subTypes;

var toRun = Factory.GetType()
            .GetMethod("CreateOutput", BindingFlags.Public | BindingFlags.Instance)
            .MakeGenericMethod(infer.Key, infer.Value)
            .Invoke(Factory,
                new object[] {callBack, Manager}) as
            ReturnItem<object>;

Factory.CreateReturnInference返回的密钥对值用于指定通用参数,只是为了明确其实现(警告非常丑陋的代码,违反开放式数量的其他东西:)):

public KeyValuePair<Type, Type> CreateReturnInference()
    {
        return this is NormalOutputFactory
            ? new KeyValuePair<Type, Type>(typeof (object), typeof (Log))
            : new KeyValuePair<Type, Type>(typeof (IEnumerable<object>), typeof (Enum));
    } 

一般问题是:通过反射调用泛型方法时如何指定Func参数?

2 个答案:

答案 0 :(得分:1)

问题是您没有正确指定Func<T>参数。换句话说,您传递给CreateOutput方法的内容类型不正确。当你这样做时:

MakeGenericMethod(infer.Key, infer.Value)

方法的类型参数

ReturnItem<TResult> CreateOutput<T, TResult>(Func<IEnumerable<T>> postBack, ...)

你传递的是typeof(IEnumerable<object>)typeof(Enum)。因为你做了

return new newKeyValuePair<Type, Type>(typeof(IEnumerable<object>), typeof(Enum));

因此,您尝试创建的CreateOutput方法具有如下签名:

ReturnItem<Enum> CreateOutput(Func<IEnumerable<IEnumerable<object>>> postBack, ...)

换句话说,T变为IEnumerable<object>TResult变为Enum。但是,传递给调用构造的泛型方法Func的{​​{1}}参数定义如下:

callback

您的解决方案是:

1)改变Func<object> callBack = () => subTypes; 的签名如下:

callback

2)或者通过调整键值对函数来更改泛型方法的参数类型。

Func<IEnumerable<IEnumerable<object>>> callBack = () => subTypes;

我认为第二个是你想要的,但我无法确定。

答案 1 :(得分:0)

我设法通过将KeyValuePair的返回值更改为:

来对其进行排序
public KeyValuePair<Type, Type> CreateReturnInference()
{
    return this is NormalOutputFactory
        ? new KeyValuePair<Type, Type>(typeof (object), typeof (object))
        : new KeyValuePair<Type, Type>(typeof (IEnumerable<object>), typeof (object));
} 

仍然不太高兴这样做,但解决了问题