编译时,Lambda表达式树始终添加System.Runtime.CompilerServices.Closure

时间:2018-07-10 15:18:42

标签: c# lambda expression-trees cil

我正在使用表达式树执行各种操作以在运行时定义方法行为。

完成编译后,我可以访问标准委托,但是生成的MethodInfo(需要再次反映)始终添加类型为

的参数
System.Runtime.CompilerServices.Closure

作为第一个参数。

这是一个简单的行为示例(我们只是对函数进行包装以调用自身,除了解释问题外,它本身没有用)。

class Program
{
    public static float SimpleOperation(float f1, float f2)
    {
        return f1 + f2;
    }

    public static LambdaExpression WrapSelf<TDelegate>(MethodInfo methodInfo)
    {
        var parameterInfoList = methodInfo.GetParameters();
        ParameterExpression[] wrappedParameters = new ParameterExpression[parameterInfoList.Length];

        for (int i = 0; i < parameterInfoList.Length; i++)
        {
            var parameterInfo = parameterInfoList[i];
            ParameterExpression inputParam = Expression.Parameter(parameterInfo.ParameterType, parameterInfo.Name);
            wrappedParameters[i] = inputParam;
        }

        Expression funcCall = Expression.Call(methodInfo, wrappedParameters.ToArray());
        return Expression.Lambda<TDelegate>(funcCall, wrappedParameters);
    }

    static void Main(string[] args)
    {
        MethodInfo methodToWrap = typeof(Program).GetMethod("SimpleOperation", BindingFlags.Public | BindingFlags.Static);

        var lambdaExpression = WrapSelf<Func<float, float, float>>(methodToWrap);

        Func<float, float, float> wrappedAddDelegate = (Func<float, float, float>)lambdaExpression.Compile();


        MethodInfo resultMethodInfo = wrappedAddDelegate.Method;


        var info = resultMethodInfo.GetParameters()[0];

        Console.ReadLine();
    }

}

所以现在所有这些都可以正确编译并执行:

float f = wrappedAddDelegate(2.0f,3.0f);

按预期返回5

现在的问题是resultMethodInfo现在有3个参数(第一个是闭包),因此签名现在是

(Closure,float,float) -> float

因此,如果我尝试使用该方法信息进行进一步的思考,则可能会使事情变得混乱。

是否有一种方法可以执行相同的任务,但是要消除结果中的闭包类型,因此我们的方法信息应保持相同的签名,例如:

 (float, float) -> float

我知道绝对可以使用Reflection.Emit来执行此操作,但是我想知道只有使用Expression tress才有解决方案。

0 个答案:

没有答案