是否可以删除您的类没有添加的VB.NET EventHandler?

plu*_*ich 9 .net c# vb.net

在我的VB.NET应用程序中,该事件AppDomain.CurrentDomain.AssemblyResolve有一个订阅它的处理程序.将ResolveEventHandler其订阅到这个活动是从我的代码加入上游(就我所知,System.AppDomain有自己Private Method订阅的事件)......是有可能从此活动中删除所有处理程序,这样我可以添加自己的处理程序和确保它是唯一的一个

基本上我正在尝试这样做:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ClassX.MethodX
Run Code Online (Sandbox Code Playgroud)

但是我不知道这个例子中是什么ClassX或者什么MethodX,因为我还没有为这个事件添加处理程序,并且这个处理程序是由上游代码添加的.我正在使用此处描述的方法来检查是否有任何处理程序是订阅事件:https: //stackoverflow.com/a/2953318/734914

编辑:我能够在调试时使用立即窗口确定订阅事件的方法.

?  DirectCast(gettype(System.AppDomain).GetField("AssemblyResolve", BindingFlags.Instance or BindingFlags.NonPublic).GetValue(AppDomain.CurrentDomain) , ResolveEventHandler)
{System.ResolveEventHandler}
    _methodBase: Nothing
    _methodPtr: 157334028
    _methodPtrAux: 1827519884
    _target: {System.ResolveEventHandler}
    **Method: {System.Reflection.Assembly ResolveAssembly**(System.Object, System.ResolveEventArgs)}
    Target: Nothing
Run Code Online (Sandbox Code Playgroud)

现在我试图删除它,就像这样,因为它不是一个Public方法:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly")
Run Code Online (Sandbox Code Playgroud)

但是这会给编译器错误说:"AddressOf参数必须是方法的名称".所以我不确定如何在这里指定非Public方法

txt*_*elp 2

来自原始评论:

这是一个关于从没有委托签名的事件中删除委托的主题..非常方便,但海报最后指出

“看起来 AppDomain.CurrentDomain.AssemblyResolve 根本不支持删除事件,因此我发布的代码将不起作用。”

甚至 .NET 也抱怨该事件只能出现在orSystem.AppDomain.AssemblyResolve的左侧(运算符是 C# ).. 所以它看起来像“不”:/+=-=+=/-=AddHandler/RemoveHandler

此外,编辑后,您无法执行以下操作的原因如下:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly")
Run Code Online (Sandbox Code Playgroud)

因为该AddressOf关键字是一个运算符关键字,类似于 a+-是一个运算符,它对AddressOf给定的过程进行操作,并且它必须是它可以在编译时推断出的过程名称。并且该GetMethod函数返回一个MethodInfo类型而不是已知的函数地址。

然而一切并没有失去!

and函数实际上需要传入一个and (使用时被编译为 a ),所以你不需要 来执行你想要的操作,你需要AddHandler一个.RemoveHandlerObjectDelegateAddressOfDelegateAddressOfDelegate

为此,我们可以使用接受对象CreateDelegate的方法。应该注意的是,由于您尝试访问私有方法,因此您需要指定 of和(我是说,但您将对它们进行按位操作),例如:MethodInfoBindFlagsReflection.BindingFlags.InstanceReflection.BindFlags.NonPublicandOr

GetType(Reflection.Assembly).GetMethod("ResolveAssembly", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
Run Code Online (Sandbox Code Playgroud)

所以调用CreateDelegate它会给我们以下代码

[Delegate].CreateDelegate(GetType(Reflection.Assembly), GetType(Reflection.Assembly).GetMethod("ResolveAssembly", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic))
Run Code Online (Sandbox Code Playgroud)

但这相当冗长,所以让我们分解一下:

Dim type As Type = GetType(Reflection.Assembly)
Dim mi As Reflection.MethodInfo = type.GetMethod("ResolveAssembly", (Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic))
Run Code Online (Sandbox Code Playgroud)

现在我们可以通过以下方式 简单地RemoveHandler调用:AppDomain.CurrentDomain.AssemblyResolve

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, [Delegate].CreateDelegate(type, mi)
Run Code Online (Sandbox Code Playgroud)

除了AppDomain.CurrentDomain.AssemblyResolve期望委托/事件签名匹配之外,因此我们需要将创建的委托转换为适当的类型:

RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, CType([Delegate].CreateDelegate(type, mi), System.ResolveEventHandler)
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过事件处理程序的反射删除私有方法。

警告!! 虽然这段代码可以编译和运行,但我不保证它的有效性或准确性,因为你(本质上)是在处理帧和堆栈指针,所以虽然它可能会运行并且可能会工作,但它也可能会产生小猫..所以要小心。

希望能有所帮助!