[обновлено для ясности]
Во-первых; приведите Expression
к MemberExpression
.
A MemberExpression
имеет две вещи, представляющие интерес:
- .Member -
PropertyInfo
/ FieldInfo
члену
- .Expression - выражение для оценки, чтобы получить "obj" для .Member
т.е. если вы можете оценить .Expression
как "obj", а .Member
- это FieldInfo
, то вы можете получить фактическое значение через .GetValue(obj)
на FieldInfo
(и PropertyInfo
очень похоже).
Проблема в том, что вычисление .Expression
очень сложно; -p
Очевидно, вам повезет, если окажется, что это ConstantExpression
- но в большинстве случаев это не так; это может быть ParameterExpression
(в этом случае вам нужно знать фактическое значение параметра, которое вы хотите оценить), или любую другую комбинацию Expression
s.
Во многих случаях простой (возможно, ленивый) вариант - использовать .Compile()
, чтобы заставить .NET Framework выполнять тяжелую работу; Затем вы можете оценить лямбду как типизированный делегат (передавая любые параметры, которые требует лямбда). Однако это не всегда вариант.
Чтобы показать, насколько это сложно; рассмотрим этот тривиальный пример (где я жестко запрограммирован на каждом этапе, а не тестирую и т. д.):
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);
}
}