2016-10-19 268 views
0

美好的一天!我想了解以下問題:C#靜態事件處理程序與非靜態事件處理程序

比方說,我們有簡單的EventSubscriber類

public class EventSubscriber 
{ 
    public static Delegate AddEventHandler(object target, string eventName, Action<object, EventArgs> action) 
    { 
     EventInfo eventInfo = target.GetType().GetEvent(eventName); 
     Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, action.Method); 
     eventInfo.AddEventHandler(target, handler); 
     return handler; 
    } 

    public static void RemoveEventHandler(object target, string eventName, Delegate handler) 
    { 
     var eventInfo = target.GetType().GetEvent(eventName); 
     eventInfo.RemoveEventHandler(target, handler); 
    } 
} 

而且我們說,我們有我們想要訂閱的事件經過的計時器。

class Program 
{ 
    static System.Timers.Timer timer; 
    public static void InitTimer(int interval) 
    { 
     timer = new System.Timers.Timer(interval); 
     timer.Start(); 
    } 
    static void Main(string[] args) 
    { 
     int interval = 1000; 
     InitTimer(interval); 
     var handler = EventSubscriber.AddEventHandler(timer, "Elapsed", Handler); 
     Thread.Sleep(Convert.ToInt16(interval * 5)); 
     EventSubscriber.RemoveEventHandler(timer, "Elapsed", handler); 
     Thread.Sleep(Convert.ToInt16(interval * 5)); 
    } 

    public static void Handler(object sender, EventArgs args) 
    { 
     Console.WriteLine("BOOO"); 
    } 
} 

現在如果你編譯這個應用程序,一切都會正常工作,你會看到應用程序的擴展行爲。 讓我們結束我們的定時器類:

public class TimerWrapper 
{ 
    public System.Timers.Timer Timer { get; set; } 
    public int Interval { get; set; } 
    public TimerWrapper(int interval) 
    { 
     Interval = interval; 
     Timer = new System.Timers.Timer(Interval); 
     Timer.Start(); 
    } 
    public static void Handler(object sender, EventArgs args) 
    { 
     Console.WriteLine("BOOO"); 
    } 
} 

現在讓我們來看看:

class Program 
{ 
    static void Main(string[] args) 
    { 
     int interval = 1000; 
     TimerWrapper timerWrapper = new TimerWrapper(interval); 
     var handler = EventSubscriber.AddEventHandler(timerWrapper.Timer, "Elapsed", TimerWrapper.Handler); 
     Thread.Sleep(Convert.ToInt16(interval * 5)); 
     EventSubscriber.RemoveEventHandler(timerWrapper.Timer, "Elapsed", handler); 
     Thread.Sleep(Convert.ToInt16(interval * 5)); 
    } 
} 

一切工作在以前的時間。但是如果我們將使TimerWrapper中的處理程序處於非靜態並運行應用程序呢?我們將接收System.ArgumentException,並顯示下一條消息「無法綁定到目標方法,因爲它的簽名或安全透明度與代理類型的兼容性不兼容。」

我有假設爲什麼這樣,但我想知道它堅定。

我希望能得到全面的答案,在此先感謝並感謝您的時間!

+0

我沒有看到你給出的代碼的例外。你確定你可以用*代碼來重現它嗎? –

+0

你做了最後一步嗎?我的意思是在TimerWrapper中的Handler必須是非靜態方法。 – Crispried

+0

啊,我錯過了。如果你真的顯示不起作用的代碼,而不是僅僅兩個* do *工作的例子,那真的很有幫助。當我有機會時會再試一次。 –

回答

2

問題是你打電話給Delegate.CreateDelegate帶有一個預計適用於靜態方法的重載(或者例如有一個額外的委託參數是方法調用目標的方法)。

所有你需要做的就是它的工作是通過在現有委託的目標,當您創建新的一個:

Delegate handler = Delegate.CreateDelegate(
    eventInfo.EventHandlerType, 
    action.Target, 
    action.Method); 

如果原來的委託(action)使用靜態方法, action.Target已經是null,所以沒關係。

+0

非常感謝,謝謝! – Crispried