C# Emit IL——将某个对象的值推入堆栈?

C# Emit IL -- push value of some object onto stack?

我创建了一个动态方法,即:

class MyClass
{
    private void object _o = <whatever>;

    void CreateDynamicMethod()
    {
       DynamicMethod dm = new DynamicMethod("Test", ...);

       // emit various IL

       // need to push _o onto stack here
    }
}

第二条评论,我想把_ocurrent的值压入栈中。我不想推送 _o 的引用,因为它会随着我构建动态方法而改变。

假设 _o = 5,我想推送 5,如果 _o 包含一个列表,我想推送它,如果它包含一个字符串,我想推送该字符串。

动态方法(Test)是静态方法,显然不会有MyClass的this指针来获取字段。我什至不能将它放在静态变量中,因为它会在执行 Test() 期间访问,而不是在我构建方法时访问。

即使我有 this 指针,_o 在 Test() 执行时也不会具有正确的值。

有什么建议吗?

您不能传递指针,因为它是无效的。但是,您可以传入一个句柄。我过去使用的一种技术是将一个整数值压入堆栈,作为一些静态可用资源(如静态 class 中的字典或网络资源,或其他任何资源)的索引,它将保存该方法将来需要它时对象的值。

顺便说一句,编译器是这样调用虚方法的。它不知道它会在编译时调用哪个版本的实例方法——它不知道。因此,代表该方法的标记被压入堆栈,而不是指向该方法本身的指针。然后,该令牌将用于在运行时使用众所周知位置的资源进行 vtable 查找,并将令牌作为该资源的索引。

完成任务所需的全部是您自己的 vtable 版本,并且您将使用整数作为标记。 Ldc.i4.s 是 IL 指令,用于将您想要的任何整数常量压入堆栈。那是你的令牌 :) 在调用静态方法检索你的对象之前将它压入堆栈。

尽管调用方法之前一定要存储对象 ;)

有一些方法可以操纵堆栈来存储序列化的代理对象,该方法可以在调用时反序列化。但是如果我在这里解释是怎么回事,我会被激怒的。