如何在表达式中获取引用类型的值?

时间:2010-03-23 20:21:55

标签: c# .net lambda

我有这个方法:

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 个答案:

答案 0 :(得分:5)

以下是答案(受阿卡什回答的启发):

LambdaExpression lambda = Expression.Lambda(methodCall.Arguments[0]);
var compiledExpression = lambda.Compile();
return compiledExpression.DynamicInvoke();

答案 1 :(得分:3)

你必须手动评估成员表达式,MemberExpression包含“Expression”,它是指定成员的容器对象,为此你可以克服你的争论的Lamda并编译并执行它。

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

所以无论你传递什么,你都会在“v”变量中得到它。

答案 2 :(得分:1)

这实际上不是值类型或引用类型的问题 - 它是一个常量表达式或非常量表达式的问题。如果你打电话

,我确定你现有的代码会失败
DoSomething(c => c.SomeMethod(DateTime.Now));

基本上,方法的参数只是一个表达式。这不是一个价值。您可以编译该表达式然后执行它以获取该时间点的值,但重要的是要理解表达式本身不是值。在常量表达式的情况下,这很容易,但是按照DateTime.Now示例,根据定义,表达式的计算值会随着时间的推移而变化:)

你想用这个论点做什么?这里的大局是什么?

答案 3 :(得分:0)

首先,乔恩说。

没有任何价值可以得到,这只是表达。可能感兴趣的是NewExpression,它具有Constructor属性;如果编译了表达式并运行了生成的委托,则此属性包含将被称为的反射构造函数。您可以手动调用该构造函数并获取用户实例化的实例。