Получение значений от ExpressionTrees

позвольте там быть:

Expression<Func<Customer, bool>> expression = c => c.Name == "John";

теперь я получаю значение при помощи:

string myvalue = ((ConstantExpression) bin.Right).Value;

теперь позвольте там быть:

string x = "John";
Expression<Func<Customer, bool>> expression = c => c.Name == x;

теперь я понимаю это

string myvalue = ((ConstantExpression) bin.Right).Value;

генерировал бы ошибку, потому что bin.right здесь не является constantexpression, это - полевое выражение, но вопрос состоит в том, как я получаю значение (John) из этого?

6
задан Stacker 11 August 2010 в 10:57
поделиться

1 ответ

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

string myvalue = Expression.Lambda<Func<string>>(bin.Right).Compile().Invoke();

Обратите внимание, что это не сработает, если параметр c используется в правой части выражения, поскольку он не будет определен. Также обратите внимание, что это даст вам текущее значение правой части при вызове Invoke, а последующие вызовы могут возвращать другие значения, если поле в объекте изменится.


Обновление: если вы не знаете тип правой части во время компиляции, вы можете использовать объект, но это не работает для таких типов значений, как int. Вам нужно будет использовать Expression.Convert для принудительной упаковки типов значений перед их возвратом. Это будет работать как для типов значений, так и для ссылочных типов:

object myvalue = Expression.Lambda<Func<object>>(
    Expression.Convert(bin.Right, typeof(object))).Compile().Invoke();

Вы также можете использовать нетипизированную лямбду и DynamicInvoke:

object myvalue = Expression.Lambda(bin.Right).Compile().DynamicInvoke();
13
ответ дан 8 December 2019 в 18:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: