动态LINQ,选择函数,适用于Enumerable,但不适用于Queryable

我一直在摆弄动态LINQ一段时间了,但我还没有了解它的秘密。

我有一个我要解析的表达式,如下所示:

"document.LineItems.Select(i => i.Credit).Sum();" 

在解析这个问题时,我需要在LineItems Collection上调用Select函数。 我正在使用Expression.Call的工厂方法:

 Expression.Call( typeof(Queryable), "Select", new Type[] { typeof(LineItem), typeof(decimal?) }, expr, Expression.Lambda(expression, new ParameterExpression[] { Expression.Parameter(typeof(LineItem) })); 

此刻

 expr: document.LineItems [ICollection] expression: LineItem.Credit [decimal?] 

这些都没有实现。 我现在正在构建表达式树。

现在,问题是:

这个Expresssion.Call抛出和exception:“没有generics方法’选择’类型’System.Linq.Queryable’与提供的类型参数和参数兼容”;

我通过改变Expression.Call的第一个参数,通过在’System.Linq.Enumerable’而不是’Queryable’中查找’Select’来轻松解决它。

但是,这并不是我想要的。 我不希望所有LineItem都只计算Sum(),这显然是Enumerable的情况。 我想要Queryable工作。

另外,对于解析的最后一部分 – Sum(),我还需要使用Enumerable Sum(),因为Queryable Sum()会抛出相同的Exception。

我已经检查了MSDN,“选择”function的两个签名是相同的,所以我真的不明白为什么一个工作而另一个不工作。

任何帮助或指针都会受到重视。

问候,

问题是LineItemsICollection ,而Queryable.Select的第一个参数需要IQueryableICollection仅实现IEnumerable ,这就是它适用于Enumerable.Select

您需要将expr的类型更改为IQueryable

您应该能够使用Queryable.AsQueryable方法执行此操作。 以下函数创建一个表达式,以对给定Document实例的credit属性值求和:

 public static Expression> CreateSumLineItemsExpr(Document document) { var docExpr = Expression.Constant(document); var itemsExpr = Expression.Property(docExpr, "LineItems"); Expression> selector = i => i.Credit; var queryableExpr = Expression.Call(typeof(Queryable), "AsQueryable", new[] { typeof(LineItem) }, itemsExpr); var selectExpr = Expression.Call(typeof(Queryable), "Select", new[] { typeof(LineItem), typeof(decimal?) }, queryableExpr, selector); var sumExpr = Expression.Call(typeof(Queryable), "Sum", null, selectExpr); return Expression.Lambda>(sumExpr); }