【问题标题】:Lambda type parameter must be derived from System.DelegateLambda 类型参数必须从 System.Delegate 派生
【发布时间】:2019-03-05 08:55:20
【问题描述】:

C# 项目中,我想创建一个扩展,该扩展将采用属性名称列表并创建一个动态选择查询。

我发现magic Gist 似乎正是这样做的。但是,var lambda = ... 不断抛出以下错误

Lambda 类型参数必须从 System.Delegate 派生

这里是代码

public static IQueryable<dynamic> ToDynamic<T>(this IQueryable<T> query, IEnumerable<String> fields)
{
    var pocoType = typeof(T);

    var itemParam = Expression.Parameter(pocoType, "x");
    var members = fields.Select(f => Expression.PropertyOrField(itemParam, f));
    var addMethod = typeof(IDictionary<string, object>).GetMethod(
                "Add", new Type[] { typeof(string), typeof(object) });


    var elementInits = members.Select(m => Expression.ElementInit(addMethod, Expression.Constant(m.Member.Name), Expression.Convert(m, typeof(object))));

    var expando = Expression.New(typeof(ExpandoObject));
    var lambda = Expression.Lambda<Expression<Func<T, dynamic>>>(Expression.ListInit(expando, elementInits), itemParam);

    return query.Select(lambda.Compile());
}

我该如何纠正这个错误?

【问题讨论】:

标签: c# lambda


【解决方案1】:

Expression.Lambda&lt;T&gt; 表达式中T 被视为lambda 类型参数必须从System.Delegate 派生。所以你只需要删除包装Expression,也不需要在最后调用Compile,因为IQueryable期望收到Expression&lt;Func&lt;T, F&gt;&gt;而不是Func&lt;T, F&gt;,它是用于IEnumerable

//..
var lambda = Expression.Lambda<Func<T, dynamic>>(Expression.ListInit(expando, elementInits), itemParam);

return query.Select(lambda);

【讨论】:

  • 谢谢!尽管var lambda = ... 不再抛出以前的异常,但我收到以下错误`LINQ to Entities 中仅支持具有单个元素的列表初始化项。` 调用方法users.ToDynamic(fields).ToList();
  • @MikeA 一个快速的解决方法是更改​​方法以返回IEnumerable&lt;dynamic&gt; 并将return 语句更改为return query.AsEnumerable().Select(lambda.Compile()); 但这意味着查询不会在数据库中执行,而是在客户端上执行
  • 做我想做的事情的全部目的是在数据库上进行选择,而不是在内存中。有没有办法在数据库服务器上做到这一点?
  • @MikeA 好吧,DictionaryExpandoObject 是不可能的,但我可以尝试使用包含键值对的列表来调查解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多