VB.NET - Übergeben eines Ereignisses als Parameter

8

Ich muss ein Ereignis als Parameter an eine Funktion übergeben. Gibt es eine Möglichkeit, dies zu tun?

Der Grund ist, dass ich eine Sequenz von zwei Zeilen Code habe, die überall in meinem Programm verstreut sind, wo ich den Handler dynamisch zu einem Event entferne und dann den Handler wieder setze. Ich mache das für mehrere verschiedene Events und Event-Handler, also habe ich beschlossen, eine Funktion zu schreiben, die das tut.

Nehmen wir zum Beispiel an, ich habe eine Combobox in meinem Code namens combobox1, und ich habe den Handler namens indexChangedHandler. An mehreren Stellen meines Codes habe ich die folgenden zwei Zeilen:

%Vor%

Nun möchte ich nicht die obigen zwei Codezeilen (oder ähnliches) in meinem gesamten Programm wiederholen, also suche ich nach einer Möglichkeit, dies zu tun:

%Vor%

so dass überall wo diese zwei Codezeilen (oder ähnlich) in meinem Programm vorkommen, kann ich sie einfach durch ersetzen:

%Vor%

Bisher gibt der "evt as Event" -Teil des Arguments der setHandler-Funktion einen Fehler.

PS: Ich habe diese Frage in einigen anderen Foren gestellt und werde immer wieder gefragt, warum ich den Handler sofort nach dem Entfernen einstellen möchte. Der Grund dafür ist, dass das dynamische Hinzufügen eines Ereignishandlers n-mal dazu führt, dass der Handler n-mal ausgeführt wird, wenn das Ereignis auftritt. Um dies zu vermeiden, dh um sicherzustellen, dass der Handler beim Auftreten des Ereignisses nur einmal ausgeführt wird, entferne ich den Handler jedes Mal, wenn ich den Handler dynamisch hinzufügen möchte.

Sie fragen sich vielleicht, warum der Handler mehrmals an erster Stelle hinzugefügt wird ... Der Grund ist, weil ich den Handler erst nach einem bestimmten Ereignis, sagen wir E1, in meinem Formular hinzugefügt habe (ich füge den Handler darin hinzu) der Handler des Ereignisses E1). Und Ereignis E1 kann mehrmals in meinem Formular vorkommen. Wenn ich den Handler nicht jedes Mal vor dem erneuten Hinzufügen lösche, wird der Handler hinzugefügt und somit mehrmals ausgeführt.

Was immer der Fall ist, die Verarbeitung, die innerhalb der Funktion stattfindet, ist für mich zu dieser Zeit nicht von äußerster Wichtigkeit, sondern nur das Mittel, ein Ereignis als Parameter zu übergeben.

    
Tracer 10.11.2010, 09:01
quelle

3 Antworten

10

Natürlich können Sie Ereignisse herumreichen ... Nun, Sie können Action(Of EventHandler) übergeben, die tun können, was Sie wollen.

Wenn Sie eine Klasse haben, die ein Ereignis wie folgt definiert:

%Vor%

Wenn Sie eine Instanz von ComboBox angegeben haben, können Sie add & amp; Entfernen Sie Handler-Aktionen wie folgt:

%Vor%

(Nun, das ist VB.NET 4.0-Code, aber Sie können dies in 3.5 mit AddressOf und ein wenig mehr mucking.)

Wenn ich also einen Handler Foo :

habe %Vor%

Und eine Raise Methode für ComboBox Ich kann das jetzt tun:

%Vor%

Dies schreibt die Nachricht "Hier drüben mit Foo!" wie erwartet.

Ich kann diese Methode auch erstellen:

%Vor%

Ich kann die Ereignishandler-Aktionen wie folgt weitergeben:

%Vor%

Was wiederum die Nachricht "Hier mit Foo!" schreibt.

Ein Problem, das ein Problem sein könnte, ist, dass Sie versehentlich die Delegierten für das Hinzufügen und Entfernen von Ereignishandlern im Code austauschen können - schließlich sind sie vom selben Typ. Es ist daher einfach, stark typisierte Delegaten für die Aktionen zum Hinzufügen und Entfernen zu definieren:

%Vor%

Der Code zum Definieren der Delegat-Instanzen ändert sich nur für die Delegattypen:

%Vor%

So können Sie jetzt sehr kreativ sein. Sie können eine Funktion definieren, die den Add-Handler-Delegaten, den Delegate-Handler-Delegaten und einen Event-Handler übernimmt, der einen Event-Handler verbindet und Ihnen dann ein IDisposable zurückgibt, mit dem Sie den Handler später ohne entfernen können Sie müssen einen Verweis auf den Event-Handler beibehalten. Dies ist praktisch für die Verwendung von Using -Anweisungen.

Hier ist die Unterschrift:

%Vor%

Mit dieser Funktion kann ich das nun tun:

%Vor%

Und das schreibt die Nachricht "Hier drüben mit Foo!" nur zweimal. Der erste und der letzte Raise -Aufruf befinden sich außerhalb des Abonnements für den Ereignishandler.

Viel Spaß!

    
Enigmativity 10.11.2010, 12:11
quelle
2

Je nach Kontext gibt es verschiedene Bedeutungen für den Begriff "Ereignis". In dem Kontext, den Sie suchen, ist ein Event ein passendes Methodenpaar, das einen Delegaten aus einer Subskriptionsliste hinzufügen oder entfernen kann. Leider gibt es in VB.NET keine Klasse zur Darstellung einer Methodenadresse ohne angehängtes Objekt. Man könnte wahrscheinlich Reflexion verwenden, um die geeigneten Methoden zu holen, und diese Methoden dann an eine Routine übergeben, die würde sie beide nennen, aber in Ihrer speziellen Situation wäre das wahrscheinlich albern.

Die einzige Situation, in der ich sehen kann, dass es nützlich sein kann, ein Ereignis in dem von Ihnen beschriebenen Sinne zu übergeben, wäre etwas wie eine IDisposable -Objekt, das Ereignisse von langlebigeren Objekten abonniert und alle seine Ereignisse abbestellen muss, wenn es entsorgt wird. In diesem Fall kann es hilfreich sein, reflection zu verwenden, um die remove-delegate-Methode für jedes Ereignis abzurufen, und anschließend alle remote-delegate-Methoden aufzurufen, wenn ein Objekt entfernt wird. Leider kenne ich keine Möglichkeit, die abzurufenden Ereignisse darzustellen, außer als String-Literale, deren Gültigkeit bis zur Laufzeit nicht überprüft werden konnte.

    
supercat 15.11.2010 19:25
quelle
2

Sie können keine Ereignisse herumreichen. Event ist kein Typ, es ist ein Schlüsselwort, das ein Methodenpaar definiert, hinzufügen und entfernen, mit dem der Status des Ereigniselements der Klasse geändert wird. Sie sind in dieser Hinsicht sehr ähnliche Eigenschaften (die Methoden get und set haben).

Wie Eigenschaften können die Methoden add und remove alles machen, was Sie wollen. In der Regel werden diese nur eine Delegat-Instanz verwalten, die wiederum ein MulticastDelegate ist, oder anders ausgedrückt, eine Liste von Delegaten, die nacheinander aufgerufen werden, wenn das Ereignis ausgelöst wird.

Sie können diese Struktur in C # deutlich sehen, wo sie nicht mit AddHandler / RemoveHandler maskiert ist, aber Sie bearbeiten direkt die Liste der zugeordneten Handler: myObject.Event += new Delegate(...); .

Und wieder wie Eigenschaften, ein Mitglied einer Klasse zu sein, die tatsächlich zwei verschiedene Methoden abstrahiert, ist es nicht möglich, ein Ereignis als Objekt wörtlich zu übergeben.

    
Bobby 10.11.2010 09:13
quelle

Tags und Links