C# 无法聚合带有Expression.AndAlso的表达式列表
我是显式构建LINQ表达式的新手,我正在尝试通过使用Aggregate和Expression.AndAlso将IEnumerable>>组合成单个表达式> 我觉得我快接近了,但我显然错过了什么C# 无法聚合带有Expression.AndAlso的表达式列表,c#,linq,lambda,expression,C#,Linq,Lambda,Expression,我是显式构建LINQ表达式的新手,我正在尝试通过使用Aggregate和Expression.AndAlso将IEnumerable>>组合成单个表达式> 我觉得我快接近了,但我显然错过了什么 public static Expression<Func<T, bool>> CombineExpressions<T>( IEnumerable<Expression<Func<T, bool>>> expressions) {
public static Expression<Func<T, bool>> CombineExpressions<T>(
IEnumerable<Expression<Func<T, bool>>> expressions)
{
if (expressions == null || expressions.Count() == 0)
{
return t => true;
}
var combined = expressions
.Cast<Expression>()
.Aggregate((a, b) => Expression.AndAlso(a, b));
ParameterExpression pe = Expression.Parameter(typeof(T), "x");
return Expression.Lambda<Func<T, bool>>(combined, pe);
}
请帮忙 为什么要重新发明轮子?优秀的LinqKit库已经通过其 以你的例子:
return expressions.Aggregate((accumulate, current) => accumulate.And(current));
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, secondBody), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
}
}
这里的问题是需要组合函数(从技术上讲,表达式表示函数)<当调用两个函数时,code>和实际上没有意义;需要对两个直接解析为布尔值的表达式调用它。您需要获得每个函数的主体,而不是整个函数,并且
还需要将这些主体组合在一起
但是仅仅抓住尸体是不够的;如果您这样做,您将遇到一个问题,即每个实体的参数都是不同的。您需要用为结果函数创建的新参数替换每个函数参数的所有用法
要处理替换这些参数,我们可以使用以下helper类和调用它的helper方法来进行替换:
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
有了这个助手方法,您已经完成了大部分工作;剩下的不多了:
public static Expression<Func<T, bool>> CombineExpressions<T>(
IEnumerable<Expression<Func<T, bool>>> expressions)
{
if (expressions == null || expressions.Count() == 0)
{
return t => true;
}
ParameterExpression param = Expression.Parameter(typeof(T), "x");
var combined = expressions
.Select(func => func.Body.Replace(func.Parameters[0], param))
.Aggregate((a, b) => Expression.AndAlso(a, b));
return Expression.Lambda<Func<T, bool>>(combined, param);
}
如果我们先花时间创建这个可重用类型,那么将它从两个函数推广到N是非常简单的:
public static Expression<Func<T, bool>> CombineExpressions<T>(
IEnumerable<Expression<Func<T, bool>>> expressions)
{
if (expressions == null || expressions.Count() == 0)
{
return t => true;
}
return expressions.Aggregate((a, b) => a.And(b));
}
公共静态表达式组合表达式(
(可数表达式)
{
if(expressions==null | | expressions.Count()==0)
{
返回t=>true;
}
返回表达式。聚合((a,b)=>a和(b));
}
从何处获得该异常?使用什么参数调用CombineeExpressions?您正在构造一个类似于someFunction&&someOtherFunction
的表达式。这可能不是你的意思。这个答案只有两票(现在)是犯罪的。我花了几个小时试图找出我的表情积累出了什么问题,结果发现我只需要单独使用表情体。
public static Expression<Func<T, bool>> CombineExpressions<T>(
IEnumerable<Expression<Func<T, bool>>> expressions)
{
if (expressions == null || expressions.Count() == 0)
{
return t => true;
}
return expressions.Aggregate((a, b) => a.And(b));
}