2008-09-25 14 views
148

Gibt es eine Möglichkeit zu sagen, ob ein Event-Handler zu einem Objekt hinzugefügt wurde? Ich serialisiere eine Liste von Objekten in/aus dem Sitzungszustand, so dass wir den SQL-basierten Sitzungszustand verwenden können ... Wenn ein Objekt in der Liste eine Eigenschaft geändert hat, muss es markiert werden, wofür der Ereignishandler zuvor sorgte . Wenn nun die Objekte deserialisiert werden, wird der Event-Handler jedoch nicht abgerufen.Wurde bereits ein Event-Handler hinzugefügt?

In einem Anfall von leichtem Ärger fügte ich nur den Ereignishandler der Get-Eigenschaft hinzu, die auf das Objekt zugreift. Es wird jetzt aufgerufen, was großartig ist, außer dass es 5 Mal aufgerufen wird, also denke ich, dass der Handler immer hinzugefügt wird, wenn auf das Objekt zugegriffen wird.

Es ist wirklich sicher genug, um einfach zu ignorieren, aber ich würde es lieber so viel sauberer machen, indem ich überprüfe, ob der Handler bereits hinzugefügt wurde, also mache ich nur einmal.

Ist das möglich?

EDIT: Ich habe nicht unbedingt die volle Kontrolle darüber, welche Event-Handler hinzugefügt werden, so ist nur die Überprüfung auf null nicht gut genug.

+0

auch sehen http://stackoverflow.com/questions/367523/how-to-ensure-a-event-ist-nur-einmal-abonniert-einmal –

Antwort

107

von außerhalb der definierenden Klasse, wie @Telos erwähnt, können Sie nur auf der Eventhandler linken Seite eines += oder -= verwenden. Wenn Sie also die definierende Klasse ändern können, können Sie eine Methode zum Durchführen der Überprüfung bereitstellen, indem Sie überprüfen, ob der Ereignishandler null ist. Wenn ja, wurde kein Ereignishandler hinzugefügt. Wenn nicht, dann vielleicht und Sie können die Werte in Delegate.GetInvocationList durchlaufen. Wenn einer dem Delegat entspricht, den Sie als Ereignishandler hinzufügen möchten, wissen Sie, dass er da ist.

Und das könnte leicht geändert werden, um "den Handler hinzuzufügen, wenn es nicht da ist". Wenn Sie keinen Zugriff auf die Innereien der Klasse haben, die das Ereignis anzeigt, müssen Sie möglicherweise die Optionen -= und += untersuchen, wie von @Lou Franco vorgeschlagen.

Sie sollten jedoch besser die Art, wie Sie diese Objekte in Betrieb nehmen und außer Betrieb nehmen, überprüfen, um zu sehen, ob Sie keine Möglichkeit finden, diese Informationen selbst zu verfolgen.

+7

Dies kompiliert nicht, EventHandler kann nur auf der linken Seite von + = oder - = stehen. – CodeRedick

+0

Ah ja. Guter Punkt. Incorporated. –

+2

Gestrichene Stimme bei weiterer Erklärung. SQL-Status zerstört hier ziemlich die gesamte Idee ... :( – CodeRedick

18

Wenn dies der einzige Handler ist, können Sie prüfen, ob das Ereignis null ist. Ist dies nicht der Fall, wurde der Handler hinzugefügt.

Ich denke, Sie können sicher - = auf das Ereignis mit Ihrem Handler aufrufen, auch wenn es nicht hinzugefügt wird (wenn nicht, könnten Sie es fangen) - um sicherzustellen, dass es nicht da ist, bevor Sie hinzufügen.

+2

Diese Logik wird abgebrochen, sobald das Ereignis auch anderswo behandelt wird. – bugged87

0
EventHandler.GetInvocationList().Length > 0 
+2

wirft dies nicht, wenn die Liste == null? –

+2

Außerhalb der Klasse, die den Event-Handler besitzt, können Sie nur - = und + = verwenden. Sie können nicht auf das Ereignis zugreifen. – tbergelt

6

Dieses Beispiel zeigt, wie mit der Methode GetInvocationList() Delegaten für alle hinzugefügten Handler abgerufen werden. Wenn Sie nachsehen, ob ein bestimmter Handler (Funktion) hinzugefügt wurde, können Sie Array verwenden.

Sie können verschiedene Eigenschaften in der Method-Eigenschaft des Delegaten untersuchen, um festzustellen, ob eine bestimmte Funktion hinzugefügt wurde.

Wenn Sie schauen, ob nur eine Datei angehängt ist, können Sie einfach auf Null testen.

+0

GetInvocationList() ist kein Mitglied meiner Klasse. Tatsächlich kann ich diese Methode auf keinem Objekt oder Handler, auf den ich Zugriff habe, finden ... – CodeRedick

+0

Ich habe den Code korrigiert. Es ist ein Mitglied des betreffenden Ereignisses. –

+0

Ich habe das auch versucht, anscheinend kann man nur von der Klasse auf das Ereignis zugreifen. Ich mache das generisch, und wie andere schon erwähnt haben, gehen Event-Handler wahrscheinlich sowieso verloren. Danke für die Klarstellung! – CodeRedick

4

Wenn ich Ihr Problem richtig verstehe, haben Sie möglicherweise größere Probleme. Sie haben gesagt, dass andere Objekte diese Ereignisse abonnieren können. Wenn das Objekt serialisiert und deserialisiert wird, verlieren die anderen Objekte (die Objekte, die Sie nicht kontrollieren) ihre Event-Handler.

Wenn Sie sich darüber keine Sorgen machen, dann sollte ein Verweis auf Ihren Event-Handler gut genug sein. Wenn Sie sich Sorgen über die Nebenwirkungen anderer Objekte machen, die ihre Event-Handler verlieren, sollten Sie Ihre Caching-Strategie überdenken.

+1

D'oh! Hatte nicht einmal daran gedacht ... obwohl es offensichtlich gewesen sein sollte, wenn man bedenkt, dass mein eigener Fehler darin bestand, dass sich mein eigener Führer verlor. – CodeRedick

141

Ich kam vor kurzem zu einer ähnlichen Situation, in der ich einen Handler für ein Ereignis nur einmal registrieren musste. Ich fand, dass Sie sicher zuerst deregistrieren können, und dann wieder anmelden, auch wenn die Prozedur nicht registriert ist:

myClass.MyEvent -= MyHandler; 
myClass.MyEvent += MyHandler; 

Beachten Sie, dass diese Sie Ihre Handler registrieren jedes Mal tun, wird dafür sorgen, dass Ihr Handler nur einmal registriert ist, . Klingt wie eine ziemlich gute Praxis für mich :)

+5

Scheint riskant; Wenn ein Ereignis nach dem Entfernen des Handlers und vor dem Zurücksetzen ausgelöst wird, wird es verpasst. – Jimmy

+18

Sicher. Du meinst es ist nicht threadsicher. Aber das kann nur ein Problem sein, wenn mehrere Threads oder ähnliches laufen, was nicht üblich ist. In den meisten Fällen sollte dies der Einfachheit halber gut genug sein. – alf

+0

Ich denke, dass dies der beste Weg ist, es einfach zu praktizieren, wenn du es addierst, subtrahiere es trotzdem, dann kannst du sicherer sein. sonst wirst du deinen Kopf zur Wand schlagen, indem du herausfindest, dass dieselbe Methode zweimal aufgerufen wird. –

0

i mit alf Antwort einverstanden, aber wenig Änderung ist es ,, zu verwenden,

  try 
      { 
       control_name.Click -= event_Click; 
       main_browser.Document.Click += Document_Click; 
      } 
      catch(Exception exce) 
      { 
       main_browser.Document.Click += Document_Click; 
      } 
Verwandte Themen