AndAlso几个表达的 (AndAlso between several Expression<

2019-07-17 11:08发布

我有3个谓语,我想作一个AndAlso之间。 我发现主板上的几个样品,但解决不了我的问题。

这些谓词是: Expression<Func<T, bool>>

我有这样的代码:

Expression<Func<T, bool>> predicate1 = ......;
Expression<Func<T, bool>> predicate2 = ......;
Expression<Func<T, bool>> predicate3 = ......;

我创建一个扩展方法,使一个“AndAlso”:

public static Expression<Func<T, bool>> AndAlso<T>(
    this Expression<Func<T, bool>> expr, 
    Expression<Func<T, bool>> exprAdd)
{
    var param = Expression.Parameter(typeof(T), "p");
    var predicateBody = Expression.AndAlso(expr.Body, exprAdd.Body);
    return Expression.Lambda<Func<T, bool>>(predicateBody, param);

    //Tried this too
    //var body = Expression.AndAlso(expr.Body, exprAdd.Body);
    //return Expression.Lambda<Func<T, bool>>(body, expr.Parameters[0]);
}

我用的是这样的:

var finalPredicate = predicate1
    .AndAlso<MyClass>(predicate2)
    .AndAlso<MyClass>(predicate3);

谓词看看这个:

当我在查询中使用:

var res =  myListAsQueryable().Where(finalPredicate).ToList<MyClass>();

我得到这个错误: 变量从范围'引用类型“BuilderPredicate.MyClass”的“P”,但它没有定义

你能告诉我什么是错的?

非常感谢,

Answer 1:

问题是创建一个新的参数 - 你可以这样做,但如果你只是把它分配给最终的λ,有您的参数,并在所提供的表达式的原始参数之间没有任何联系。 试着改变表达式的PARAM名称,然后检查finalPredicate 。 你会看到类似这样的:

{p => (((x.Age == 42) AndAlso (y.Salary == 50)) AndAlso z.FirstName.StartsWith("foo"))}

现在的问题是显而易见的。

马克Gravell建议在这个答案一般Expression.AndAlso ,而这正是你所需要的:

public static Expression<Func<T, bool>> AndAlso<T>(
    this Expression<Func<T, bool>> expr1,
    Expression<Func<T, bool>> expr2)
{
    // need to detect whether they use the same
    // parameter instance; if not, they need fixing
    ParameterExpression param = expr1.Parameters[0];
    if (ReferenceEquals(param, expr2.Parameters[0]))
    {
        // simple version
        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(expr1.Body, expr2.Body), param);
    }
    // otherwise, keep expr1 "as is" and invoke expr2
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(
            expr1.Body,
            Expression.Invoke(expr2, param)), param);
}

(由Marc代码,而不是我)



文章来源: AndAlso between several Expression> : referenced from scope