Expression API抛出异常:变量' x'类型' x'从范围''引用,但未定义

时间:2014-09-05 19:08:34

标签: c# .net lambda expression expression-trees

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

我希望actual具有与左操作数相同的值,并且expected具有与右操作数相同的值。

但是,此代码会抛出InvalidOperationException,并显示以下消息:

  

变量&#39; person&#39;类型&#39;人物&#39;引用范围&#39;&#39;,但未定义。

如何解决此异常?

1 个答案:

答案 0 :(得分:3)

您没有将参数传递给您第二次创建的lambda,这是您第一次使用的方式。在构造lambda时需要指出有一个参数,并在调用时传入该值。

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