When you compile a lambda expression, you get a delegate with a Closure parameter.

c# expression-trees lambda


In my usageExpression.Lambda( ... ).Compile() The outcome is a delegate with the first parameter being Closure, which is what is needed to generate a delegate from an expression tree.

public static Func<T, T, T> CreateTest<T>()
    ParameterExpression a = Expression.Parameter( typeof( T ) );
    ParameterExpression b = Expression.Parameter( typeof( T ) );
    Expression addition = Expression.Add( a, b );

    return (Func<T, T, T>)Expression.Lambda( addition, a, b ).Compile();


// 'addition' equals
// Int32 lambda_method(
//     System.Runtime.CompilerServices.Closure,
//     Int32,
//     Int32 )
Func<int, int, int> addition = DelegateHelper.CreateTest<int>();
int result = addition( 5, 5 );

Without giving a parameter, I can simply invoke the delegate using standard code.Closure so where does this come fromClosure arrive at?

How do I dynamically invoke this delegate?

// The following does not work.
// Exception: MethodInfo must be a runtime MethodInfo object.    
MethodInfo additionMethod = addition.Method;
int result = (int)additionMethod.Invoke( null, new object[] { 5, 5 } );

It seems from expression trees that I must pass theClosure object.

PropertyInfo methodProperty
    = typeof( Delegate ).GetProperty( "Method", typeof( MethodInfo ) );
MemberExpression getDelegateMethod
    = Expression.Property( Expression.Constant( addition ), methodProperty );
Func<MethodInfo> getMethodInfo
    = (Func<MethodInfo>)Expression.Lambda( getDelegateMethod ).Compile();
// Incorrect number of arguments supplied for call to method
// 'Int32 lambda_method(System.Runtime.CompilerServices.Closure, Int32, Int32)'
Expression call
    = Expression.Call(
        Expression.Constant( 5 ), Expression.Constant( 5 ) );

This is a condensed example that is illogical on its own. In reality, I want to be able to wrap things, like.Func<Action<SomeObject>> with Func<Action<object>> . For delegates that are not nested, I can already accomplish this. This is helpful while you're reflecting, zzz-48 zzz.

How do I setup this properly?Closure entity, or how can I stop it from existing?

10/29/2011 3:07:46 PM

Accepted Answer

The Closure The kind you see is an use specific. In the MSDN, it is stated rather plainly:

This API supports the .NET Framework infrastructure and is not intended to be used directly from your code. Represents the runtime state of a dynamically generated method.

A state might exist in an expression tree.

All of the nonliteral constants that the lambda expression, well, closes over, are included in the Closure instance. It may also have a series of delegates for expression trees with nested lambdas.

The expression tree compiler employs a charming little method to do this. It creates code in memory using aDynamicMethod something is static by definition. Yet they are producing a shuttered over its first disagreement delegate. This means that you are not have to give the delegate's target field as the static method's first parameter since the CLR will do it for you. effectively avoiding your knowledge of the Closure argument.

The answer to your difficulty is straightforward: instead of attempting to call the method, invoke the delegate by using either Delegate.DynamicInvoke when using reflection or Expression.Invoke when using an expression tree.

5/29/2013 10:47:02 AM

Related Questions

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow