Expression.Lambda: Variable 'x' of type '' referenced from scope '', but it is not defined
Asked Answered
E

2

6

I saw connected topic but...

I was attempting to implement specification pattern. If I create the Or or And Expression explicitly with the System.Linq.Expressions API, I will get the error

InvalidOperationExpression variable 'x' referenced from scope.

For example ,this is my code

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

EDITED

I tried to use Specification pattern with Linq to Nhibernate so in a my work code it looks like:

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

So I want to use code like this x => x.Id > 4.

Edited

So my solution is

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

Thank you @Jon Skeet

Exorcism answered 19/3, 2012 at 22:13 Comment(0)
S
7

Each of those bodies has a separate set of parameters, so using just secondCondition.Parameters doesn't give firstCondition.Body a parameter.

Fortunately, you don't need to write all of this yourself at all. Just use PredicateBuilder by Joe Albahari - it's all done for you.

Smaragdite answered 19/3, 2012 at 22:19 Comment(0)
A
4

If you are interested, this is the Expression tree you have to use:

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());
Abstracted answered 19/3, 2012 at 22:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.