在编制委托lambda表达式的结果与封闭的说法 [英] Compiling a lambda expression results in delegate with Closure argument

查看:195
本文介绍了在编制委托lambda表达式的结果与封闭的说法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用 Expression.Lambda(...).Compile(),以创建一个表达式树的委托,结果是一个代表其的第一个参数是 关闭 < 。/ A>

When I use Expression.Lambda( ... ).Compile() in order to create a delegate from an expression tree, the result is a delegate of which the first argument is Closure.

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 );



我可以方便地调用通过普通的代码,委托没有通过关闭的对象,但如果没有这种关闭从何而来?

I can easily call the delegate through ordinary code without passing a Closure object, but where does this Closure come from?

我怎样才能把这个委托动态?

How can I call this delegate dynamically?

// 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 } );

使用表达式目录树,它看起来像我必须通过关闭对象。

Using expression trees it looks like I have to pass the Closure 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(
        getMethodInfo(),
        Expression.Constant( 5 ), Expression.Constant( 5 ) );

这是一个简单的例子就没有意义了在自己的权利。什么我其实想实现是要能包住如 Func键<作用< SomeObject>> Func键<作用<对象>> 。我已经可以对非嵌套的代表做到这一点。这是反思,因为这里讨论过程中非常有用。

This is a simplified example which doesn't make sense in its own right. What I am actually trying to achieve is to be able to wrap e.g. Func<Action<SomeObject>> with Func<Action<object>>. I can already do this for non nested delegates. This is useful during reflection, as discussed here.

我应该如何正确初始化该关闭对象,我怎么防止它在那里?

How should I correctly initialize this Closure object, or how do I prevent it from being there?

推荐答案

关闭输入你看到的是一个实现细节。该 MSDN 是相当明确一下:

The Closure type you see is an implementation detail. The MSDN is pretty explicit about it:

此API支持.NET Framework基础结构,而不是
适合直接在代码中使用。表示一个动态生成方法的运行时间
状态。

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.

这是表达式树可以有一个状态。

An expression tree can have a state.

闭包实例将包含所有非字面常量lambda表达式,那么,关闭了过来。它也可以包含代表在表达式树lambda表达式嵌套的链条。

The Closure instance will contain all the non literal constants that the lambda expression, well, closes over. It can also contain a chain of delegates for nested lambdas in expression trees.

要实现这一目标,表达式树编译器使用一个可爱的小把戏。它使用 DynamicMethod的,也就是定义静态生成在内存中的代码。然而,他们正在创建一个代表就是关闭了它的第一个参数 。这意味着CLR会委托的目标字段传递为静态方法的第一个参数,所以你不必。从而有效地隐藏从你的Closure的说法。

To achieve this, the expression tree compiler uses a cute little trick. It generates in memory code using a DynamicMethod, that is by definition static. Yet, they're creating a delegate that is "closed over its first argument". Meaning that the CLR will pass the target field of the delegate as a first argument of the static method, so you don't have to. Effectively hiding the Closure argument from you.

你的问题的解决方案很简单,不要试图通过使用的 Delegate.DynamicInvoke 当你使用反射,或的 Expression.Invoke 在表达式树的情况下。

The solution to your problem is simple, don't try to call the method, invoke the delegate, either by using Delegate.DynamicInvoke when you're using reflection, or Expression.Invoke in the context of an expression tree.

这篇关于在编制委托lambda表达式的结果与封闭的说法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆