Как получить значение ссылочного типа в выражении? - PullRequest
4 голосов
/ 23 марта 2010

У меня есть этот метод:

public void DoSomething<T>(Expression<Func<T, object>> method)
{
}

Если этот метод вызывается так:

DoSomething(c => c.SomeMethod(new TestObject()));

... как получить значение параметра, который был передан в SomeMethod ()?

Если параметр является типом значения, это работает:

var methodCall = (MethodCallExpression)method.Body;
var parameterValue = ((ConstantExpression)methodCall.Arguments[0]).Value;

Однако, когда я передаю ссылочный тип, methodCall.Arguments [0] является MemberExpression, и я не могу понять, как написать код, чтобы получить значение из него.

Ответы [ 4 ]

5 голосов
/ 24 марта 2010

Вот ответ (вдохновленный ответом Акаша):

LambdaExpression lambda = Expression.Lambda(methodCall.Arguments[0]);
var compiledExpression = lambda.Compile();
return compiledExpression.DynamicInvoke();
3 голосов
/ 24 марта 2010

Вы должны будете оценить выражение члена вручную, MemberExpression содержит «Expression», который является контейнерным объектом указанного члена, для этого вы можете создать Lamda вашего аргумента, скомпилировать и выполнить его.

LamdaExpression l = Expression.Lambda(methodCall.Arguments[0]);
var c = l.Compile();
var v = c.Invoke();

Итак, что бы вы ни пропустили, вы получите его в переменной "v".

1 голос
/ 23 марта 2010

Это на самом деле не вопрос типа значения или ссылочного типа - это вопрос постоянного или неконстантного выражения. Я уверен, что ваш существующий код потерпит неудачу, если вы позвоните

DoSomething(c => c.SomeMethod(DateTime.Now));

также.

По сути, аргумент метода - это просто выражение. Это не ценность. Вы можете потенциально скомпилировать это выражение и затем выполнить его, чтобы получить значение в тот момент времени, но важно понимать, что выражение не является значением само по себе. В случае константного выражения это легко, но на примере DateTime.Now по определению оцененное значение выражения изменяется со временем:)

Что вы пытаетесь сделать с аргументом? Какая здесь более широкая картина?

0 голосов
/ 23 марта 2010

Во-первых, что сказал Джон.

Нет значений, за которые нужно держаться, это всего лишь выражения. Что может представлять интерес - это NewExpression, который имеет свойство Constructor; это свойство содержит отраженный конструктор, который будет называться , если вы скомпилируете выражение и запустите полученный делегат. Вы можете вручную вызвать этот конструктор и получить экземпляр того, что пользователь намеревался создать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...