表达式.Lambda:变量';x';类型'';引用自scope'';,但是它没有被定

本文关键字:引用 变量 Lambda 类型 表达式 scope | 更新日期: 2023-09-27 18:28:14

我看到了连接的主题,但。。。

我试图实现规范模式。如果我使用System.Linq.Expressions API显式创建Or或And表达式,我将得到错误

从作用域引用了InvalidOperationExpression变量"x"。

例如,这是我的代码

public class Employee
{
    public int Id { get; set; }
}
Expression<Func<Employee, bool>> firstCondition = x => x.Id.Equals(2);
Expression<Func<Employee, bool>> secondCondition = x => x.Id > 4;

Expression predicateBody = Expression.OrElse(firstCondition.Body, secondCondition.Body);
Expression<Func<Employee, bool>> expr = 
    Expression.Lambda<Func<Employee, bool>>(predicateBody, secondCondition.Parameters);
Console.WriteLine(session.Where(expr).Count()); - //I got error here

编辑

我试着将规范模式与Linq一起用于Nhibernate,所以在我的工作代码中,它看起来像:

ISpecification<Employee> specification = new AnonymousSpecification<Employee>(x => x.Id.Equals(2)).Or(new AnonymousSpecification<Employee>(x => x.Id > 4));
var results = session.Where(specification.is_satisfied_by());

所以我想使用这样的代码x=>x.Id>4。

已编辑

所以我的解决方案是

 InvocationExpression invokedExpr = Expression.Invoke(secondCondition, firstCondition.Parameters);
var expr = Expression.Lambda<Func<Employee, bool>>(Expression.OrElse(firstCondition.Body, invokedExpr), firstCondition.Parameters);
Console.WriteLine(session.Where(expr).Count());

谢谢@Jon Skeet

表达式.Lambda:变量';x';类型'';引用自scope'';,但是它没有被定

这些实体中的每一个都有一组单独的参数,因此仅使用secondCondition.Parameters不会给firstCondition.Body一个参数。

幸运的是,你根本不需要自己写所有这些。只需使用Joe Albahari的PredicateBuilder,一切都为您完成。

如果您感兴趣,这是您必须使用的表达式树:

var param = Expression.Parameter(typeof(Employee), "x");
var firstCondition = Expression.Lambda<Func<Employee, bool>>(
    Expression.Equal(
        Expression.Property(param, "Id"),
        Expression.Constant(2)
    ),
    param
);
var secondCondition = Expression.Lambda<Func<Employee, bool>>(
    Expression.GreaterThan(
        Expression.Property(param, "Id"),
        Expression.Constant(4)
    ),
    param
);
var predicateBody = Expression.OrElse(firstCondition.Body, secondCondition.Body);
var expr = Expression.Lambda<Func<Employee, bool>>(predicateBody, param);
Console.WriteLine(session.Where(expr).Count());