2010-10-29 83 views
1

是否有可能使用Reflection是C#来触发一个事件?说我有这样的情况: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?我已经试过这个,只是得到例外。

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

回答

3

假设您目前的情况,即:

  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方法内部可能存在任意代码,“触发”事件的逻辑也可能与任何事情有关。可能甚至没有支持多播delgate字段来存储侦听器。

在任何情况下,试图告诉物体发射事件几乎总是一个主要设计缺陷的标志,IMO。如果您仍然真的想这样,这将是更好的声明这样的方法在你的类:

public void RaiseXXXEvent() { ... } 
+0

哈!有用!非常感谢。任何原因,我想使用动态调用只是调用? – Ben 2010-10-29 03:57:12

+0

// @本:干杯。 'System.Delegate'不声明'Invoke'方法。 – Ani 2010-10-29 04:03:11

+0

令人惊叹!刚才我尝试用'BindingFlags.Instance'只是因为我认为这个事件是'public'。但是我得到了'FieldInfo [0]'。为什么? – 2010-10-29 04:03:59