Ist es möglich, einen VB.NET EventHandler zu entfernen, den Ihre Klasse nicht hinzugefügt hat?

9

In meiner VB.NET-Anwendung hat das Ereignis AppDomain.CurrentDomain.AssemblyResolve einen Handler abonniert. Der ResolveEventHandler , der dieses Ereignis abonniert hat, wurde vor meinem Code hinzugefügt (soweit ich weiß, System.AppDomain hat sein eigenes Private Method für das Event abonniert) ... ist es möglich, alle Handler von diesem Event zu entfernen, damit ich meinen eigenen Handler hinzufügen und sicherstellen kann, dass es nur eins ist?

Im Wesentlichen versuche ich das zu tun:

%Vor%

Aber ich weiß nicht, was ClassX oder MethodX in diesem Beispiel sind, weil ich noch keinen Handler zu diesem Event hinzugefügt habe, und dieser Handler wurde vom Upstream-Code hinzugefügt. Ich verwende die hier beschriebene Methode, um zu überprüfen, ob ein Handler ein abonniertes Ereignis ist: Ссылка

Bearbeiten: Ich konnte herausfinden, welche Methode das Ereignis abonniert hat, indem ich das Direktfenster während des Debugging verwende.

%Vor%

Jetzt versuche ich, es zu entfernen, weil es keine öffentliche Methode ist:

%Vor%

Aber das gibt einen Compiler-Fehler, der besagt: "AddressOf-Parameter muss der Name einer Methode sein". Ich bin mir also nicht sicher, wie ich hier eine nicht-öffentliche Methode angeben soll

    
plukich 03.02.2015, 00:17
quelle

1 Antwort

1

Aus dem ursprünglichen Kommentar:

Hier ist ein Thema zum Entfernen von Teilnehmern von Ereignissen, die Sie nicht tun. Ich habe die Unterschrift des Delegierten zu .. ziemlich praktisch, aber am Ende sagte das Plakat

  

"Es sieht so aus, als ob AppDomain.CurrentDomain.AssemblyResolve das Entfernen von Ereignissen überhaupt nicht unterstützt, so dass der von mir gepostete Code nicht funktioniert."

Sogar .NET beschwert sich, dass das Ereignis System.AppDomain.AssemblyResolve nur auf der linken Seite von += oder -= erscheinen kann ( +=/-= Operatoren sind die C # AddHandler/RemoveHandler ) ... also sieht es wie ein 'nein aus ': /

Außerdem können Sie nach Ihren Änderungen Folgendes nicht tun:

%Vor%

Dies liegt daran, dass das Schlüsselwort AddressOf ein Keyword ist Operator-Schlüsselwort, ähnlich einem + oder - ist ein Operator, der AddressOf operiert mit der angegebenen Prozedur und muss ein Prozedur-Name sein, den er zur Kompilierungszeit ableiten kann. Und die GetMethod -Funktion gibt ein MethodInfo Typ und keine bekannte Funktionsadresse.

Alles ist jedoch nicht verloren!

Die AddHandler und RemoveHandler Funktionen erfordern tatsächlich ein Object und Delegate to übergeben werden ( AddressOf wird in ein Delegate kompiliert, wenn es verwendet wird), so dass Sie nicht das AddressOf brauchen, um das zu tun, was Sie wollen, Sie brauchen ein Delegate .

Dazu können wir die CreateDelegate Methode, die ein MethodInfo Objekt verwendet. Da Sie versuchen, auf private Methoden zuzugreifen, müssen Sie die BindFlags von Reflection.BindingFlags.Instance und Reflection.BindFlags.NonPublic (Ich sage and , aber Sie werden eine bitweise Or auf ihnen tun), Beispiel:

%Vor%

Wenn Sie also CreateDelegate aufrufen, erhalten Sie folgenden Code:

%Vor%

Aber das ist ziemlich ausführlich, also lasst uns das durchbrechen:

%Vor%

Und jetzt können wir das RemoveHandler auf AppDomain.CurrentDomain.AssemblyResolve einfach über folgendes aufrufen:

%Vor%

Außer AppDomain.CurrentDomain.AssemblyResolve erwartet die Übereinstimmung von Delegat / Ereignissignaturen. Daher müssen wir den erstellten Delegaten in den entsprechenden Typ umwandeln:

%Vor%

Sie können nun eine private Methode durch Reflektion aus dem Ereignishandler entfernen.

ACHTUNG !! Während dieser Code kompiliert und ausgeführt wird, mache ich keine Garantie für seine Gültigkeit oder Genauigkeit, da Sie mit Frame- und Stack-Zeigern (im Wesentlichen) herumfummeln, und so während laufen könnte und es könnte funktionieren, es kann auch Babykätzchen spawn .. also sei einfach vorsichtig.

Hoffe, das kann helfen!

    
txtechhelp 18.07.2015, 10:02
quelle

Tags und Links