【问题标题】:Cannot Convert between Expression<Func<...>> and Func<...>无法在 Expression<Func<...>> 和 Func<...> 之间转换
【发布时间】:2016-01-14 01:18:59
【问题描述】:

我尝试调用的方法(第三方,无法更改)需要 Func&lt;TResult&gt;。使用反射我正在尝试制作一个例如Func&lt;Task&lt;IEnumerable&lt;Person&gt;&gt;&gt; 但我无意中创建了一个Expression&lt;Func&lt;Task&lt;IEnumerable&lt;Person&gt;&gt;&gt;&gt;。反思的原因是 person 是任意的,可以是任何类型,具体取决于调用方式/时间。

// trying to mimic this hard-code: () => TaskEx.FromResult(Enumerable.Empty<Person>())
//var enumerableType = typeof(Person); //potentially

var empty = (typeof(Enumerable)).GetMethod("Empty");
var genereicEmpty = empty.MakeGenericMethod(enumerableType);
var emptyEnumerable = genereicEmpty.Invoke(null, null);

var fromResult = typeof (TaskEx).GetMethod("FromResult");
var genericFromResult = fromResult.MakeGenericMethod(genereicEmpty.ReturnType);

var enumerableTask = genericFromResult.Invoke(null, new [] {emptyEnumerable});

var functype = typeof(Func<>).MakeGenericType(genericFromResult.ReturnType);
var body = Expression.Constant(enumerableTask);
var lambdaType = typeof(Expression).GetMethods()
    .Where(x => x.Name == "Lambda")
    .Where(x => x.GetParameters().Length == 2)
    .Where(x => x.GetParameters()[1].ParameterType == typeof(ParameterExpression[]))
    .Single(x => x.IsGenericMethod);
var genericLambdaType = lambdaType.MakeGenericMethod(functype);
var lambda = genericLambdaType.Invoke(null, new object[] { body, new ParameterExpression[0] });

当我稍后使用 lambda 时,我得到了异常

Exception thrown: 'System.ArgumentException' in mscorlib.dll

Additional information: Object of type 'System.Linq.Expressions.Expression`1[System.Func`1[System.Threading.Tasks.Task`1[System.Collections.Generic.IEnumerable`1[DC.Dataloader.Models.Person]]]]' cannot be converted to type 'System.Func`1[System.Threading.Tasks.Task`1[System.Collections.Generic.IEnumerable`1[DC.Dataloader.Models.Person]]]'.

有没有比Expression.Lambda 更好的方法来即时构建Func&lt;&gt;?我似乎找不到正确的方法来做到这一点。

谢谢

【问题讨论】:

    标签: c# .net generics reflection lambda


    【解决方案1】:

    您正在寻找 .Compile() 方法,它正是这样做的。

    旁注:
    您不需要使用反射调用Expression API;你可以使用非通用的Expression.Lambda(),它仍然会返回一个Func&lt;T&gt;

    Expression.Lambda(body).Compile()
    

    【讨论】:

    • 完美!不敢相信它就在我的眼皮底下。很高兴也摆脱了 typeof(Func&lt;&gt;)lambdaType/genericLambdaType 查询。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多