Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法聚合带有Expression.AndAlso的表达式列表_C#_Linq_Lambda_Expression - Fatal编程技术网

C# 无法聚合带有Expression.AndAlso的表达式列表

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) {

我是显式构建LINQ表达式的新手,我正在尝试通过使用Aggregate和Expression.AndAlso将IEnumerable>>组合成单个表达式>

我觉得我快接近了,但我显然错过了什么

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));
}