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