C#反射:如何调用EventInfo?
如何调用EventInfo后面的事件? 我尝试了以下方法,但“GetRaiseMethod”始终为“null”: 谢谢:) 更新:这似乎是C#中的一个bug 只有在未覆盖添加\删除的情况下实现事件时,“调用”事件才有意义:C#反射:如何调用EventInfo?,c#,events,reflection,C#,Events,Reflection,如何调用EventInfo后面的事件? 我尝试了以下方法,但“GetRaiseMethod”始终为“null”: 谢谢:) 更新:这似乎是C#中的一个bug 只有在未覆盖添加\删除的情况下实现事件时,“调用”事件才有意义: class Test { public event Action TestEvent; void Invoke() { // fine TestEvent(); } } 但是,使用自定义添加\删除调用事件的概念没有意
class Test {
public event Action TestEvent;
void Invoke() {
// fine
TestEvent();
}
}
但是,使用自定义添加\删除调用事件的概念没有意义:
class Test {
public event Action TestEvent
{
add { }
remove { }
}
void Invoke() {
// does not compile, invoke what?
TestEvent();
}
}
所以事件调用只是调用底层编译器生成的委托字段的语法糖,用于具有“默认”实现的事件
知道了这一点,您可以搜索该字段并调用它。这是一个与事件同名的专用字段:
class Program {
static void Main(string[] args) {
var test = new Test();
test.TestEvent += OnTest;
var backingField = typeof(Test).GetField("TestEvent", BindingFlags.Instance | BindingFlags.NonPublic);
var delegateInstance = (Action)backingField.GetValue(test);
delegateInstance();
}
private static void OnTest() {
Console.WriteLine("Event invoked");
}
}
class Test {
public event Action TestEvent;
}
也就是说,某些.NET语言的编译器可能会为自动实现的事件生成“Raise”方法。如果是这种情况-
GetRaiseMethod
将返回这样的方法。不过,C#编译器不会这样做。所以,如果您希望安全,您可以首先调用GetRaiseEvent
,如果它返回null,则返回字段方法。当然,您应该期望字段也为null(因为并非所有事件都是如上所述的可调用的-不需要这样的字段存在)。这不是一个错误,而是一个设计决策:事实上,事件与编译器还生成支持字段的自动属性非常相似。如果以长格式指定事件,则不会生成任何字段。另一条注释:其他.NET语言(如VB.NET)确实明确支持raise方法。但是,C#不支持这一点,而是强制开发人员直接使用事件的支持字段。
class Program {
static void Main(string[] args) {
var test = new Test();
test.TestEvent += OnTest;
var backingField = typeof(Test).GetField("TestEvent", BindingFlags.Instance | BindingFlags.NonPublic);
var delegateInstance = (Action)backingField.GetValue(test);
delegateInstance();
}
private static void OnTest() {
Console.WriteLine("Event invoked");
}
}
class Test {
public event Action TestEvent;
}