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?
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 :)