Частичная оценка ConstantExpression в ExpressionTreeVisitor - PullRequest
1 голос
/ 27 марта 2010

Я не являюсь мастером дерева выражений в любом воображении, у меня есть код, который выглядит следующим образом:

    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 реализованы все интерфейсы IQueryProvider, IQueryable, которые можно ожидать от поставщика LINQ.

Когда я оцениваю дерево выражений, все идет по плану, пока я не прочитал ConstantExpression для «external», и в этот момент я не могу понять, как двигаться вперед, потому что:

      //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 ]

4 голосов
/ 27 марта 2010

Ваше выражение захватывает локальную переменную 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 голос
/ 30 июля 2011

Я предпочитаю что-то подобное. Он носит более общий характер и будет работать в ряде случаев.

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