I want to use expression trees to dynamically create a method to call a lambda. The following code runs fine for the first call to the ComposeLambda function, but the second call fails with the following error message.
Incorrect number of arguments supplied for call to method '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;
}
How can I get and pass on this closure object?
Don't use
Expression.Call(innerLambda.GetMethodInfo(), ...)
, that's just asking for trouble. Invoke the delegate instead - you have no business messing around with the delegate's "method" - not only do you lose the target (quite important in instance methods), but you're also violating privacy (anonymous methods are internal or private, for example).And in this case, you didn't pass the closure parameter to the method :) This should be rather obvious from the error message - it shows you the signature of the actual method (which includes the closure).
If you use
Expression.Invoke
(as you should with delegates), it works as expected:In addition to this, if you know the proper delegate type at compile-time, don't use
Delegate
. In this case, it's pretty trivial to useFunc<int, int>
, which you can then invoke ascomposedLambda2(0)
, for example: