在我的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方法
来自原始评论:
这是一个关于从没有委托签名的事件中删除委托的主题..非常方便,但海报最后指出
“看起来 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)
现在,您可以通过事件处理程序的反射删除私有方法。
警告!! 虽然这段代码可以编译和运行,但我不保证它的有效性或准确性,因为你(本质上)是在处理帧和堆栈指针,所以虽然它可能会运行并且可能会工作,但它也可能会产生小猫..所以要小心。
希望能有所帮助!