Подтвердить что ты не робот

Учитывая тип ExpressionType.MemberAccess, как получить значение поля?

Я разбираю дерево выражений. Учитывая NodeType выражения ExpressionType.MemberAccess, как мне получить значение этого поля?

В документах MSDN MSDN: MemberAccess - это A node, который представляет чтение из поля или свойства.

Фрагмент кода будет невероятно, невероятно полезным. Спасибо заранее.

Мой код выглядит примерно так:

public static List<T> Filter(Expression<Func<T, bool>> filterExp) 
{
//the expression is indeed a binary expression in this case
BinaryExpression expBody = filterExp.Body as BinaryExpression;

if (expBody.Left.NodeType == ExpressionType.MemberAccess) 
  //do something with ((MemberExpressionexpBody.Left).Name

//right hand side is indeed member access. in fact, the value comes from //aspdroplist.selectedvalue            
if (expBody.Right.NodeType == ExpressionType.MemberAccess)
{
   //how do i get the value of aspdroplist.selected value?? note: it non-static                        
}

//return a list
}
4b9b3361

Ответ 1

[обновлено для ясности]

Первый; введите Expression в MemberExpression.

A MemberExpression имеет две вещи, представляющие интерес:

  • . Член - PropertyInfo/FieldInfo члену
  • .Expression - выражение для оценки для получения "obj" для .Member

то есть. если вы можете оценить .Expression на "obj", а .Member - FieldInfo, вы можете получить фактическое значение через .GetValue(obj) на FieldInfoPropertyInfo очень похоже).

Проблема в том, что оценка .Expression очень сложна; -p

Очевидно, вам повезет, если он окажется ConstantExpression - но в большинстве случаев это не так; это может быть ParameterExpression (в этом случае вам нужно знать фактическое значение параметра, которое вы хотите оценить) или любую другую комбинацию Expression s.

Во многих случаях простой (возможно, ленивый) вариант заключается в использовании .Compile(), чтобы получить платформу .NET для тяжелой работы; вы можете затем оценить лямбда как типизированный делегат (передавая любые параметры, которые требуется лямбда). Однако это не всегда вариант.

Чтобы показать, насколько это сложно; рассмотрим этот тривиальный пример (где я жестко закодирован на каждом шагу, а не тестировании и т.д.):

using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo
{
    public string Bar { get; set; }
}

static class Program
{
    static void Main()
    {
        Foo foo = new Foo {Bar = "abc"};
        Expression<Func<string>> func = () => foo.Bar;

        MemberExpression outerMember = (MemberExpression)func.Body;
        PropertyInfo outerProp = (PropertyInfo) outerMember.Member;
        MemberExpression innerMember = (MemberExpression)outerMember.Expression;
        FieldInfo innerField = (FieldInfo)innerMember.Member;
        ConstantExpression ce = (ConstantExpression) innerMember.Expression;
        object innerObj = ce.Value;
        object outerObj = innerField.GetValue(innerObj);
        string value = (string) outerProp.GetValue(outerObj, null);    
    }

}

Ответ 2

Большое вам спасибо Марку Гравелю выше. Я очень оценил его помощь.

Получается, в моем случае. проблема может быть решена с помощью:

object value = Expression.Lambda(expBody.Right).Compile().DynamicInvoke();

Еще раз спасибо Mark!