Reputation: 2866
public class Program
{
private static void Main()
{
ContrivedComparer.Compare<Person>(person => person.Name == "Calvin");
}
}
public class Person
{
public string Name { get; set; }
}
public class ContrivedComparer
{
// this likely looks highly ill-advised out of context but this is contrived.
public static readonly object comparatePerson = new Person { Name = "Ted" };
public static void Compare<TComparate>(Expression<Func<TComparate, bool>> predicate)
{
if (predicate.Compile()((TComparate)comparatePerson)) return;
var expression = (BinaryExpression)predicate.Body;
var actual = Expression.Lambda(expression.Left).Compile().DynamicInvoke();
var expected = Expression.Lambda(expression.Right).Compile().DynamicInvoke();
}
}
I expect actual
to have the same value as the left operand and for expected
to have the same value as the the right operand.
However, this code throws an InvalidOperationException
with the following message:
variable 'person' of type 'Person' referenced from scope '', but it is not defined.
How can I resolve this exception?
Upvotes: 0
Views: 519
Reputation: 203829
You aren't passing the parameter to the lambda that you're creating the second time, the way that you are the first time. You need to indicate that there is a parameter when constructing the lambda and pass in the value when invoking it.
public static void Compare<TComparate>(Expression<Func<TComparate, bool>> predicate)
{
if (predicate.Compile()((TComparate)comparatePerson)) return;
var expression = (BinaryExpression)predicate.Body;
var actual = Expression.Lambda(expression.Left, predicate.Parameters)
.Compile().DynamicInvoke(comparatePerson);
var expected = Expression.Lambda(expression.Right, predicate.Parameters)
.Compile().DynamicInvoke(comparatePerson);
}
Upvotes: 3