2009-06-12 9 views
2

ich über den folgenden Code oft kommen:Anmeldung zu einer Veranstaltung für die Dauer eines mit Block

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

Das ist großartig, aber es wäre schön, wenn wir dies in einem schöneren Weg machen können. Ich dachte an wie etwas zu tun:

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

Leider ist dieses von C# verboten ist, weil myService.SomeEvent nur auf der linken Seite eines + = oder erscheinen können - = (aus gutem Grund). Meine Frage ist, welche anderen Möglichkeiten habe ich? Im Idealfall würde Ich mag diese Art sicher sein, die Reflexion Regeln und die folgenden Aktionen ausführen (was ich bereits implementiert haben):

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

Um klar zu sein, ich bin nicht verheiratet, die ‚mit‘ Syntax zu verwenden und man könnte argumentieren, dass es eine Perversion der Sprache ist. Andere Optionen würden geschätzt werden!

+0

Ja, es sieht so aus, als ob Sie am besten eine Zeichenfolge übergeben und daraus ein EventInfo-Objekt erstellen. – Noldorin

+0

Ich hatte gehofft, dass das nicht der Fall war ... es funktioniert gut, aber es ist nicht ideal. – jonnii

+1

Als eine Frage des Stils, würde ich versuchen - endlich dafür. Das betont, dass die _semantics_ der Operation "abonnieren Sie das Ereignis, tun Sie das Ding, immer abbestellen". Die Verwendung eines wegwerfbaren Gegenstandes betont "dieses Ding hat Ressourcen, die aggressiv aufgeräumt werden müssen". Ich mag es nicht, Programm-Semantik mit Aufräum-Mechanismen zu mischen. Ich glaube nicht, dass ich bis zur "Perversion" gehen würde, aber es ist zumindest eine schlecht riechende Praxis. –

Antwort

2

Wahrscheinlich gibt es eine Möglichkeit, dies mit sauberer Syntax zu tun, aber wenn Sie eine Struktur wie diese haben ...

public struct ActionDisposable : IDisposable 
{ 
    private readonly Action _action; 

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

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

... und ein Verfahren wie folgt aus:

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

That würden Sie Code wie folgt schreiben:

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

Oder wie folgt aus:

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

Zurück gehen und Antworten auf einige meiner alten Fragen markieren. Dies ist der beste der verfügbaren Antworten ... – jonnii

2

Sind Sie besorgt, dass das Ereignis wegen einer Ausnahme oder etwas nicht abgemeldet wird? Wenn ja, könntest du versuchen/endlich. Ansonsten denke ich, dass der ursprüngliche Weg der Beste ist und mir gut geht.

+0

Genau aus diesem Grund. Ich könnte try/finally verwenden, was genau ein Verwendungsblock ist (irgendwie). – jonnii

+2

Die using-Anweisung schlägt IDisposable Semantik für mich vor, während die try/finally suggeriert, dass Sie sich über eine Ausnahme Sorgen machen. Ich würde mit versuchen/endlich gehen. – PeterAllenWebb

Verwandte Themen