ExpressionTreeVisitor中ConstantExpression的部分评估

时间:2010-03-27 16:21:12

标签: c# .net linq expression-trees

我不是任何想象力的表达树大师,我所拥有的代码看起来像这样:

    int external = 10;
    using(var session = new Session())
    {
       session.Add(new Product { Name = "test1", Price = 20 });
       session.Add(new Product {Name = "test", Price = 10});
       var product = session.Products.Where(p => p.Price == external).FirstOrDefault();
       Assert.Equal(10, product.Price);
    }

Session实现了LINQ Provider所期望的所有IQueryProvider,IQueryable接口。

当我评估表达式树时,一切都会进行计划,直到我读到“外部”的ConstantExpression,此时,我对如何前进感到茫然,因为:

      //constant is ConstantExpression for "external" on the right side of the "p.Price == external" expression above.
      var t = constant.GetType(); //evaluates to class called "<>c__DisplayClass2" - with a member named "external" that has the value 10. 

问题基本上是..我怎样才能访问成员“外部”的值 - 有没有办法在不使用反射的情况下完成此操作?还是我煮熟了?我错过了什么?

2 个答案:

答案 0 :(得分:4)

您的表达式捕获external局部变量,这就是编译器隐式创建匿名类型以包装捕获的变量的原因。相等的右侧部分不是ConstantExpression,它实际上是MemberExpression,其Expression属性是ConstantExpression类型<>c__DisplayClass2

您可以按如下方式访问该属性的值:

MemberExpression memberExpr = /* right-hand side of the equality */ as MemberExpression;
ConstantExpression constantExpr = memberExpr.Expression as ConstantExpression;
PropertyInfo prop = memberExpr.Member as PropertyInfo;
object value = prop.GetValue(constantExpr.Value, null);

答案 1 :(得分:1)

我更喜欢这样的东西。它更为通用,适用于许多情况。

var operation = (BinaryExpression)predicate.Body;
var righthandValue= Expression.Lambda(operation.Right).Compile().DynamicInvoke();