Phi*_*mer 3 .net c# linq lambda expression-trees
我想使用表达式树动态创建一个方法来调用lambda.第一次调用ComposeLambda函数时,以下代码运行正常,但第二次调用失败,并显示以下错误消息.
为调用方法'Int32 lambda_method(System.Runtime.CompilerServices.Closure,Int32)提供的参数数量不正确
{
Func<int, int> innerLambda = i => i + 1;
var composedLambda = ComposeLambda(innerLambda);
Console.WriteLine(composedLambda.DynamicInvoke(0));
var composedLambda2 = ComposeLambda(composedLambda);
Console.WriteLine(composedLambda2.DynamicInvoke(0));
}
private static Delegate ComposeLambda(Delegate innerLambda)
{
Func<int, int> outerLambda = i => i + 2;
var parameter = Expression.Parameter(typeof (int));
var callInner = Expression.Call(innerLambda.GetMethodInfo(), parameter);
var callOuter = Expression.Call(outerLambda.GetMethodInfo(), callInner);
var composedLambdaType = typeof (Func<,>).MakeGenericType(typeof (int), typeof (int));
var composedLambdaExpression = Expression.Lambda(composedLambdaType, callOuter, parameter);
var composedLambda = composedLambdaExpression.Compile();
return composedLambda;
}
Run Code Online (Sandbox Code Playgroud)
如何获取并传递此闭包对象?
不要使用Expression.Call(innerLambda.GetMethodInfo(), ...)
,这只是在寻找麻烦.相反,调用委托 - 你没有业务搞乱委托的"方法" - 你不仅失去了目标(在实例方法中非常重要),而且你也违反了隐私(匿名方法是内部或私人的,例如).
在这种情况下,您没有将closure参数传递给方法:)这应该从错误消息中显而易见 - 它向您显示实际方法的签名(包括闭包).
如果你使用Expression.Invoke
(和代表一样),它按预期工作:
void Main()
{
Func<int, int> innerLambda = i => i + 1;
var composedLambda = ComposeLambda(innerLambda);
Console.WriteLine(composedLambda.DynamicInvoke(0));
var composedLambda2 = ComposeLambda(composedLambda);
Console.WriteLine(composedLambda2.DynamicInvoke(0));
}
private static Delegate ComposeLambda(Delegate innerLambda)
{
Func<int, int> outerLambda = i => i + 2;
var parameter = Expression.Parameter(typeof (int));
var callInner = Expression.Invoke(Expression.Constant(innerLambda), parameter);
var callOuter = Expression.Invoke(Expression.Constant(outerLambda), callInner);
var composedLambdaType = typeof (Func<,>).MakeGenericType(typeof (int), typeof (int));
var composedLambdaExpression = Expression.Lambda(composedLambdaType, callOuter, parameter);
var composedLambda = composedLambdaExpression.Compile();
return composedLambda;
}
Run Code Online (Sandbox Code Playgroud)
除此之外,如果您在编译时知道正确的委托类型,请不要使用Delegate
.在这种情况下,使用起来非常简单Func<int, int>
,您可以调用它composedLambda2(0)
,例如:
private static Func<int, int> ComposeLambda(Func<int, int> innerLambda)
{
Func<int, int> outerLambda = i => i + 2;
var parameter = Expression.Parameter(typeof (int));
var callInner = Expression.Invoke(Expression.Constant(innerLambda), parameter);
var callOuter = Expression.Invoke(Expression.Constant(outerLambda), callInner);
var composedLambdaExpression = Expression.Lambda<Func<int, int>>(callOuter, parameter);
return composedLambdaExpression.Compile();
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4030 次 |
最近记录: |