并且还在几个Expression <Func >之间:从范围引用

我有3个谓词,我想在AndAlso之间做一个AndAlso 。 我在板上发现了几个样本,但无法解决我的问题。

这些谓词是: Expression<Func>

我有这个代码:

 Expression<Func> predicate1 = ......; Expression<Func> predicate2 = ......; Expression<Func> predicate3 = ......; 

我创建了一个扩展方法来创建一个“AndAlso”:

 public static Expression<Func> AndAlso( this Expression<Func> expr, Expression<Func> exprAdd) { var param = Expression.Parameter(typeof(T), "p"); var predicateBody = Expression.AndAlso(expr.Body, exprAdd.Body); return Expression.Lambda<Func>(predicateBody, param); //Tried this too //var body = Expression.AndAlso(expr.Body, exprAdd.Body); //return Expression.Lambda<Func>(body, expr.Parameters[0]); } 

我这样用:

 var finalPredicate = predicate1 .AndAlso(predicate2) .AndAlso(predicate3); 

谓词看起来像这样: 在此处输入图像描述

当我在查询中使用时:

 var res = myListAsQueryable().Where(finalPredicate).ToList(); 

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

你能告诉我什么是错的吗?

非常感谢,

问题是创建一个新参数 – 您可以这样做,但如果您只是将其分配给最终的lambda,则您的参数与提供的表达式中的原始参数之间没有任何关联。 尝试更改表达式的param名称,然后检查finalPredicate 。 你会看到类似的东西:

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

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

Marc Gravell在这个答案中建议一个普通的Expression.AndAlso ,这正是你需要的:

 public static Expression> AndAlso( this Expression> expr1, Expression> 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>( Expression.AndAlso(expr1.Body, expr2.Body), param); } // otherwise, keep expr1 "as is" and invoke expr2 return Expression.Lambda>( Expression.AndAlso( expr1.Body, Expression.Invoke(expr2, param)), param); } 

(代码来自Marc,不是我)