我正在使用表达式树执行各种操作以在运行时定义方法行为。
完成编译后,我可以访问标准委托,但是生成的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才有解决方案。