在动态事件处理程序中引用'this'

时间:2021-07-22 03:18:26

In my 'myClass' class, I am using Reflection.Emit to dynamically write an event handler for one of the myClass class' members.

在我的'myClass'类中,我使用Reflection.Emit为myClass类的一个成员动态编写一个事件处理程序。

I have done this successfully.

我成功完成了这个。

Now, I want to modify the event handler to call one of the instance methods in the myClass class.

现在,我想修改事件处理程序以调用myClass类中的一个实例方法。

However, I cannot figure out how to push a reference to 'this' onto the MSIL stack using Reflection.Emit. Within the event handler, Ldarg_0 is not a reference to 'this', but rather the first parameter of the event handler.

但是,我无法弄清楚如何使用Reflection.Emit将对'this'的引用推送到MSIL堆栈。在事件处理程序中,Ldarg_0不是对“this”的引用,而是事件处理程序的第一个参数。

Does anyone know how to push a reference to 'this' on the stack so that I can call an instance method. For example, this is what I would want the c# code to look like:

有谁知道如何在堆栈上推送'this'的引用,以便我可以调用实例方法。例如,这就是我希望c#代码看起来像:

public class myClass
{
private myObj1 obj1;
public myClass() {
   this.init();
}

private void init()
{
   obj1.myEvent += new myEvent_EventHandler(theHandler);
}

private void theHandler(myObj2 obj2, myObj3 obj3)
{
   // this is the part I'm having trouble with
   this.myFunction(obj2);
}

private void myFunction(myObj2 obj2)
{
   // irrelevant
}
}

Thanks!

2 个解决方案

#1


When you use Reflection.Emit (and I'm presuming DynamicMethod here), you get to choose what the first argument to the generated code will be, and it can be passed implicitly by the delegate, like this:

当你使用Reflection.Emit(我在这里假设DynamicMethod)时,你可以选择生成代码的第一个参数是什么,它可以由委托隐式传递,如下所示:

using System;
using System.Reflection.Emit;

public class App
{
    static void Main()
    {
        DynamicMethod m = new DynamicMethod("test", typeof(void),
            new[] { typeof(App), // <-- type of first argument, your choice
                typeof(string) });

        var cg = m.GetILGenerator();

        cg.Emit(OpCodes.Ldarg_0);
        cg.Emit(OpCodes.Ldarg_1);
        cg.EmitCall(OpCodes.Call,
            typeof(App).GetMethod("ShowString"), null);

        cg.Emit(OpCodes.Ret);

        Action<string> d = (Action<string>) 
            m.CreateDelegate(typeof(Action<string>), 
            new App()); // <-- this is the first argument, *your* choice

        MyEvent += d;

        // Trigger event
        MyEvent("Hello there");
    }

    static event Action<string> MyEvent;

    public void ShowString(string s)
    {
        Console.WriteLine(s);
    }
}

#2


If you are in main, then there is no instance of your Main class. The main function is static.

如果您在main中,则没有Main类的实例。主要功能是静态的。

#1


When you use Reflection.Emit (and I'm presuming DynamicMethod here), you get to choose what the first argument to the generated code will be, and it can be passed implicitly by the delegate, like this:

当你使用Reflection.Emit(我在这里假设DynamicMethod)时,你可以选择生成代码的第一个参数是什么,它可以由委托隐式传递,如下所示:

using System;
using System.Reflection.Emit;

public class App
{
    static void Main()
    {
        DynamicMethod m = new DynamicMethod("test", typeof(void),
            new[] { typeof(App), // <-- type of first argument, your choice
                typeof(string) });

        var cg = m.GetILGenerator();

        cg.Emit(OpCodes.Ldarg_0);
        cg.Emit(OpCodes.Ldarg_1);
        cg.EmitCall(OpCodes.Call,
            typeof(App).GetMethod("ShowString"), null);

        cg.Emit(OpCodes.Ret);

        Action<string> d = (Action<string>) 
            m.CreateDelegate(typeof(Action<string>), 
            new App()); // <-- this is the first argument, *your* choice

        MyEvent += d;

        // Trigger event
        MyEvent("Hello there");
    }

    static event Action<string> MyEvent;

    public void ShowString(string s)
    {
        Console.WriteLine(s);
    }
}

#2


If you are in main, then there is no instance of your Main class. The main function is static.

如果您在main中,则没有Main类的实例。主要功能是静态的。