C#反射:如何调用EventInfo?

C#反射:如何调用EventInfo?,c#,events,reflection,C#,Events,Reflection,如何调用EventInfo后面的事件? 我尝试了以下方法,但“GetRaiseMethod”始终为“null”: 谢谢:) 更新:这似乎是C#中的一个bug 只有在未覆盖添加\删除的情况下实现事件时,“调用”事件才有意义: class Test { public event Action TestEvent; void Invoke() { // fine TestEvent(); } } 但是,使用自定义添加\删除调用事件的概念没有意

如何调用EventInfo后面的事件? 我尝试了以下方法,但“GetRaiseMethod”始终为“null”:

谢谢:)

更新:这似乎是C#中的一个bug

只有在未覆盖添加\删除的情况下实现事件时,“调用”事件才有意义:

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;
}