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
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:
Wenn Sie also CreateDelegate
aufrufen, erhalten Sie folgenden Code:
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:
Außer AppDomain.CurrentDomain.AssemblyResolve
erwartet die Übereinstimmung von Delegat / Ereignissignaturen. Daher müssen wir den erstellten Delegaten in den entsprechenden Typ umwandeln:
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!