繁体   English   中英

使用反射到静态类的AddEventHandler

[英]AddEventHandler using reflection to a static class

我需要向静态类的现有事件添加新方法。 这是我的“猫”静态类,无法更改,因为它是第三方。 我需要添加新方法以在同一事件myEvent触发。 问题说明了如何对非静态类执行此操作。 但是我不确定静态类该怎么做。 有人帮忙吗?

public static class Cat
{
 internal static event EventHandler myEvent;

public static init()
{
....
....
}

}

class Dog
{
 public static void init()
 {
   EventInfo eventInfo = typeof(Cat).GetEvent("myEvent");

      if (eventInfo != null)
      {
       Delegate handler =  Delegate.CreateDelegate(eventInfo.EventHandlerType, , newMethod); // I'm stuck here
       eventInfo.AddEventHandler(, handler);  // I'm stuck here

     }
 }

  static void newMethod()
  {

  }
}

如果myEvent是公共的,则可以执行Cat.myEvent+= new EventHandler(newMethod); 但不幸的是它是internal

您应该添加一些内容。 首先,将BindingFlags添加到GetEvent ,因为该事件是静态的并且是非公开的。 默认情况下, GetEvent仅返回公共实例事件:

EventInfo eventInfo = typeof(Cat).GetEvent("myEvent", BindingFlags.Static | BindingFlags.NonPublic);

其次,使用CreateDelegate另一重载来创建一个静态方法的委托,该方法具有两个参数。 或者使用您的参数,将null作为第二个参数。

第三,使用null作为AddEventHandler的第一个参数。 通常,您将实例作为第一个参数传递,但是由于此事件是静态的,因此不需要实例:

eventInfo.AddEventHandler(null, handler);  

您并没有走的很远,但是当您尝试使用AddEventHandler()时,您将遇到很大的困难。 即使您尝试通过反射破解事件,CLR也会强制事件的可访问性。 而且由于它不是public ,所以反思将无济于事。

您必须伸手去拿更大的武器。 假设事件不是自定义的,并且月亮在右象限中,则C#编译器生成一个add访问器方法。 这是一个名为add_myEvent()的方法。 一定要使用反编译器来验证名称,确保它实际上不是那样命名的。

您要做的第一件事是为事件处理程序提供正确的签名,该签名与委托类型匹配:

    static void newMethod(object sender, EventArgs e) {
        // etc..
    }

然后,您可以编写反射代码,如下所示:

    public static void init() {
        EventInfo eventInfo = typeof(Cat).GetEvent("myEvent",
            BindingFlags.NonPublic | BindingFlags.Static);
        MethodInfo adder = typeof(Cat).GetMethod("add_myEvent",
            BindingFlags.NonPublic | BindingFlags.Static);
        MethodInfo target = typeof(Dog).GetMethod("newMethod", 
            BindingFlags.NonPublic | BindingFlags.Static);
        Delegate handler =  Delegate.CreateDelegate(eventInfo.EventHandlerType, target);
        adder.Invoke(null, new object[] { handler });
    }

由于Dog在您的控制之下,因此不需要Delegate.CreateDelegate。

此代码按预期工作:

namespace ConsoleApplication1
{

    public static class Cat
    {
        internal static event EventHandler myEvent;

        public static void RaiseEvent()
        {
            if (myEvent != null) myEvent(typeof(Cat), EventArgs.Empty);
        }
    }


    class Dog
    {
        public static void init()
        {
            MethodInfo addInfo = typeof(Cat).GetMethod("add_myEvent", BindingFlags.NonPublic | BindingFlags.Static);
            EventHandler handler = new EventHandler(Handler);
            addInfo.Invoke(null, new object[] { handler });
        }

        static void Handler(object sender, EventArgs e)
        {
            Console.WriteLine("Event fired");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Dog.init();
            Cat.RaiseEvent();
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM