AddEventHandler使用对静态类的反射
本文关键字:反射 静态类 AddEventHandler | 更新日期: 2023-09-27 18:21:40
我需要将新方法附加到静态类的现有事件中。这是我的"猫"静态类,不能更改它,因为它是第三方。我需要添加新的方法来触发同一事件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
您没有走多远,但当您尝试使用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 });
}
您应该添加一些内容。首先,将BindingFlags
添加到GetEvent
中,因为该事件是静态且非公共的。默认情况下,GetEvent
只返回公共实例事件:
EventInfo eventInfo = typeof(Cat).GetEvent("myEvent", BindingFlags.Static | BindingFlags.NonPublic);
其次,使用CreateDelegate
的另一个重载来委托一个静态方法,即具有两个参数的方法。或者使用您的,将null作为第二个参数。
第三,使用null
作为AddEventHandler
的第一个参数。通常情况下,您将实例作为第一个参数传递,但由于此事件是静态的,因此不需要实例:
eventInfo.AddEventHandler(null, handler);
由于狗在您的控制之下,因此不需要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();
}
}
}