C#反思:如何调用EventInfo?

时间:2018-03-29 06:41:02

标签: c# events reflection

如何调用EventInfo背后的事件? 我试过以下但“GetRaiseMethod”总是“空”:

MethodInfo eventRaiseMethod = eventInfos[i].GetRaiseMethod();
eventRaiseMethod.Invoke(this, arrayOfPropertyChangedArgs);

谢谢:)

更新:似乎是C#中的一个错误???

EventInfo.GetRaiseMethod() always null

1 个答案:

答案 0 :(得分:2)

"调用"事件只有在没有覆盖add \ remove:

的情况下实现事件才有意义
class Test {
    public event Action TestEvent;

    void Invoke() {
        // fine
        TestEvent();
    }
}

但是,使用自定义add \ remove调用事件的概念没有意义:

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 - 则回退到字段方法。当然你应该期望field也是null(因为并非如上所述所有事件都是可调用的 - 不需要存在这样的字段)。