C# 动态LINQ,Select函数,用于可枚举但不可查询
我已经摆弄动态LINQ有一段时间了,但我还没有了解它的秘密 我有一个要解析的表达式,如下所示:C# 动态LINQ,Select函数,用于可枚举但不可查询,c#,linq,iqueryable,expression,enumerable,C#,Linq,Iqueryable,Expression,Enumerable,我已经摆弄动态LINQ有一段时间了,但我还没有了解它的秘密 我有一个要解析的表达式,如下所示: "document.LineItems.Select(i => i.Credit).Sum();" 在解析这个过程中,我到达了需要调用LineItems集合上的Select函数的点。我正在使用factory表达式方法。调用: Expression.Call( typeof(Queryable), "Select", new Type[] { typeof(LineIte
"document.LineItems.Select(i => i.Credit).Sum();"
在解析这个过程中,我到达了需要调用LineItems集合上的Select函数的点。我正在使用factory表达式方法。调用:
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<LineItem>]
expression: LineItem.Credit [decimal?]
expr:document.LineItems[ICollection]
表达式:LineItem.Credit[十进制?]
这些都还没有实现。我现在正在构建表达式树
现在,问题是:
此Expression.Call引发异常:“System.Linq.Queryable”类型上的泛型方法“Select”与提供的类型参数和参数不兼容”
我通过更改Expression.Call的第一个参数,在“System.Linq.Enumerable”中查找“Select”,而不是“Queryable”,从而轻松解决了这个问题
但是,这并不是我想要的。我不希望所有的行项目都只是为了计算Sum(),这显然是Enumerable的情况。我想让Queryable去工作
另外,对于解析-Sum()的最后一部分,我还需要使用Enumerable Sum(),因为Queryable Sum()会引发相同的异常
我已经检查了MSDN,“选择”函数的两个签名都是相同的,所以我真的不明白为什么一个可以工作而另一个不行
欢迎提供任何帮助或指点
关于,问题在于,
行项目
是一个ICollection
,而可查询的第一个参数。Select
需要一个IQueryable
ICollection
仅实现IEnumerable
,这就是为什么它适用于Enumerable。选择
您需要将expr
的类型更改为IQueryable
您应该能够使用Queryable.AsQueryable
方法来实现这一点。以下函数创建一个表达式,对给定的文档
实例的信贷属性值求和:
public static Expression<Func<decimal?>> CreateSumLineItemsExpr(Document document)
{
var docExpr = Expression.Constant(document);
var itemsExpr = Expression.Property(docExpr, "LineItems");
Expression<Func<LineItem, decimal?>> 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<Func<decimal?>>(sumExpr);
}
public静态表达式CreateSumLineItemsExpr(文档)
{
var docExpr=Expression.Constant(文档);
var itemsexxpr=Expression.Property(docExpr,“LineItems”);
表达式选择器=i=>i.信用;
var queryableExpr=Expression.Call(typeof(Queryable),“AsQueryable”,new[]{typeof(LineItem)},itemsepr);
var selectExpr=Expression.Call(typeof(Queryable),“Select”,new[]{typeof(LineItem),typeof(decimal?},queryableExpr,selector);
var sumExpr=Expression.Call(typeof(Queryable),“Sum”,null,selectExpr);
返回表达式.Lambda(sumExpr);
}
答案很好,我怀疑是这样的。我甚至试着在LineItems集合中调用AsQueryable,但它对我没有帮助。我怎样才能安全地将expr更改为IQueryable?@MilosMijatovic-我认为AsQueryable
应该可以工作,我已经更新了答案以包含一个示例。