我有这个方法:
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,我似乎无法弄清楚如何编写代码来获取它的值。
答案 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
属性;如果编译了表达式并运行了生成的委托,则此属性包含将被称为的反射构造函数。您可以手动调用该构造函数并获取用户实例化的实例。