2010-10-29 84 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