【发布时间】:2010-03-09 18:35:58
【问题描述】:
我错过了明显的:如何访问 lambda 表达式树中的参数值?
场景:对于委托 x,我动态创建一个 lambda 表达式,其表达式树体与委托 x 具有相同的签名。在 lamdba 的主体内,我进行了一些验证、检查、记录工作(这只是测试代码,而不是生产代码),然后我使用原始参数调用原始委托 x。如果委托有返回值,它也会被返回。
效果很好(包括将参数传递给原始委托)。
但是,如果我想访问传递给委托/lambda 的原始参数值,我会碰壁。
伪代码:
var del = new Func<string, int>(_=> {return 42;});
var paramDefs = Array.ConvertAll<ParameterInfo, ParameterExpression>(del.Method.GetParameters(), _ => { return Expression.Parameter(_.ParameterType, _.Name); });
var variableTest = Expression.Variable(typeof(string), "str");
var expression = Expression.Block(
new [] { variableTest },
// this line assigns the actual run time value (which is what I need) of the parameter to the variable - but I cannot hardcode the index.
//Expression.Assign(variableTest, paramDefs[0])
// this line would assigns the ParameterExpression object (causing a run-time exception since the type of the variable is string) ... I need the _value_ of the first (or nth) parameter.
Expression.Assign(variableTest, Expression.ArrayIndex(Expression.Constant(paramDefs), Expression.Constant(0)))
);
var lamdba = Expression.Lambda(del.GetType(), expression, "foo", paramDefs);
var del2 = lamdba.Compile() as Func<string, int>;
del2("this is a test");
【问题讨论】:
-
注释掉的代码似乎是正确的,所以我会这样做。你说你不能对索引进行硬编码。为什么不?在我看来,这样就可以了。
-
我已经更改了代码。我最初想遍历表达式树 (Expression.Loop) 中的 paramDefs,逐个访问每个参数。由于代码适用于任何委托类型,因此对索引进行硬编码是行不通的。我将循环结构从表达式树中拉出来。对于具有 5 个参数的委托,我现在只需生成五个表达式(最简单的情况是将每个参数值复制到 object[])。但是,最初的问题仍然困扰着我——有没有办法从 ParameterExpression 实例中获取实际值?
标签: c# delegates lambda c#-4.0 expression-trees