使用Reflection.Emit在堆栈上使用MethodInfo实例调用方法

时间:2010-08-20 03:09:39

标签: c# cil reflection.emit methodinfo

我使用Reflection.Emit构建数学表达式解析器(例如2+2)。类接受中缀表达式(例如2+2),将其转换为后缀表达式(例如2 2 +),然后另一个类将该后缀表达式编译为IL并创建DynamicMethod。从那里开始,表达式可以被评估为在编译时以类似的速度创建它。

此编译器还支持隐式乘法,因此x(2 + 2)之类的值为x * (2 + 2)

现在,我正在尝试实现用户定义的函数(例如f(x))。当我尝试区分隐式乘法(如上所示)和用户定义函数时,会出现问题。一个示例是,如果用户输入x(5),我如何知道他们是想将x乘以5,还是使用x参数调用5函数{1}}?

要解决此问题,在前一种情况下,编译器会在IL流中插入if语句。它调用一个函数来确定函数是否使用标识符x定义。如果有,则通过MethodInfo变量和本地变量将out实例插入堆栈。

我的实际问题是,是否可以使用堆栈上的MethodInfo实例执行一个方法,该方法与编译期间调用IlGenerator.Emit(OpCodes.Call, MethodInfo)的速度相当?

感谢。

1 个答案:

答案 0 :(得分:1)

我所知道的唯一方法是允许您在堆栈上调用MethodInfo实例,方法是在其上调用Invoke方法。我相信你已经意识到了这种可能性,但你担心它可能太慢了。我建议你尝试一下,并在压力下表现时间。您可能会发现它足够快以达到您的目的。

如果不是,那么您将不得不考虑如何重构您的设计,以便您不会传递MethodInfo个实例。例如,您可以改为传递托管函数指针。这些是ldftnldvirtftn指令返回的内容。然后,您可以使用calli指令来调用其中一个。您需要使用SignatureHelper class构建calli期望作为操作数的“呼叫站点描述”。