2009-06-12 92 views
2

我經常遇到下面的代碼的持續時間的事件:訂閱了使用塊

myService.SomeEvent += listener; 
myService.DoSomething(); 
myService.SomeEvent -= listener; 

這是偉大的,但它會是很好,如果我們能做到這一點的一個更好的方式。我想在做類似的:

using(EventScope.Start(myService.SomeEvent, listener)){ 
    myService.DoSomething(); 
} 

不幸的是,這是由C#禁止,因爲myService.SomeEvent只能出現在一個+ =或左邊 - =(有很好的理由)。我的問題是我有什麼其他選擇?理想情況下,我想這是類型安全的,這就排除了反射和做以下(這我已經實現):

using(EventScope.Start(myService, "SomeEvent", listener){ 
    myService.DoSomething(); 
} 

要清楚我沒有結婚,以使用「使用」語法,並且可以說你可以說這是對語言的顛覆。其他選項將不勝感激!

+0

是的,它看起來最好的結果就是傳遞一個字符串並從中構造一個EventInfo對象。 – Noldorin 2009-06-12 18:32:32

+0

我當時希望情況並非如此......它工作正常,但並不理想。 – jonnii 2009-06-12 18:39:47

+1

作爲一個風格問題,我會用try-finally來解決這個問題。這強調,該操作的_semantics_是「訂閱事件,做事情,總是取消訂閱」。使用一次性物品強調「這件事有需要積極清理的資源」。我不喜歡混合程序語義和清理機制。我認爲我不會像「變態」那樣遠,但至少是一種糟糕的嗅覺行爲。 – 2009-06-13 05:40:51

回答

2

有可能是一個辦法用更清晰的語法要做到這一點,但如果你有這樣的結構...

public struct ActionDisposable : IDisposable 
{ 
    private readonly Action _action; 

    public ActionDisposable(Action action) 
    { 
     _action = action; 
    } 

    public void Dispose() 
    { 
     _action(); 
    } 
} 

......像這樣的方法:

public static IDisposable EventScope(Action subscribe, Action unsubscribe) 
{ 
    subscribe(); 
    return new ActionDisposable(unsubscribe); 
} 

那將讓你寫這樣的代碼:

using (EventScope(() => myService.SomeEvent += listener,() => myService.SomeEvent -= listener)) 
{ 
    myService.DoStuff(); 
} 

或者這樣:

myService.SomeEvent += listener 
using (new ActionDisposable(() => myService.SomeEvent -= listener)) 
{ 
    myService.DoStuff(); 
} 
2

您是否擔心該事件不會因爲異常或其他原因而取消訂閱?如果是這樣,你可以使用try/finally。否則,我認爲原來的方式是最好的,對我來說看起來很好。