簡體   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