【问题标题】:C# Create a Delegate that fires an event?C# 创建一个触发事件的委托?
【发布时间】:2025-12-28 10:30:16
【问题描述】:

是否可以使用 Reflection is C# 来触发事件?假设我有这样的情况:

public delegate void SomeEventHandler(object sender, BenArgs e);

class EventHub
{
    public event SomeEventHandler SOME_EVENT;

    public void fireEvent(String eventName)
    {
        SomeEventHandler evt = (SomeEventHandler) Delegate.CreateDelegate(typeof(SomeEventHandler), this, eventName);

        evt.Invoke(null, null);
    }
}

如果我打电话的意思

EventHub.fireEvent("SOME_EVENT")

然后它使事件中心触发 SOME_EVENT?我已经尝试过了,只是遇到了异常。

这主要是我的好奇心,我知道在这种情况下我可以轻松地触发事件而无需反射。

【问题讨论】:

    标签: c# events reflection delegates


    【解决方案1】:

    假设您当前的情况,即:

    1. 类场事件。
    2. 支持委托字段与事件同名。
    3. (this, EventArgs.Empty) 是传递给委托的有效参数。

    你可以这样做(需要更多的参数验证):

    public void fireEvent(String eventName)
    {
        // Get a reference to the backing field
        var del = (Delegate)typeof(EventHub)
                    .GetField(eventName, BindingFlags.NonPublic | BindingFlags.Instance)
                    .GetValue(this);
    
         // Invoke the delegate, it's invocation-list will contain the listeners
         if(del != null)
            del.DynamicInvoke(this, EventArgs.Empty);
    }
    

    用法:

      var eHub = new EventHub();
      eHub.SOME_EVENT += delegate { Console.WriteLine("SOME_EVENT fired.."); };      
      eHub.fireEvent("SOME_EVENT");
    

    现在,如果您愿意,您可以在object 上使用扩展方法来概括这个想法,但所有这些都是一个非常糟糕的想法。这个问题在一般情况下无法解决,因为人们不知道事件是如何“实施”的。 addremove 方法中可能有任意代码,“触发”事件的逻辑也可以是任何东西。甚至可能没有支持多播委托字段来存储侦听器。

    无论如何,试图告诉一个对象触发一个事件几乎总是一个重大设计缺陷的标志,IMO。如果你仍然真的想要这个,最好在你的类中声明一个这样的方法:

    public void RaiseXXXEvent() { ... } 
    

    【讨论】:

    • 哈!有用!非常感谢。有什么理由我想使用动态调用而不是调用?
    • @Ben:干杯。 System.Delegate 没有声明 Invoke 方法。
    • 太棒了!刚才我尝试使用BindingFlags.Instance 只是因为我认为该事件是public。但我得到FieldInfo[0]。为什么?
    • @Danny Chen:该事件是公开的,但支持委托字段是私有的。
    • @Ani:为什么会有“支持委托字段”?你能提供一个链接来解释这个吗?非常感谢。