在我的VB.NET应用程序中,事件AppDomain.CurrentDomain.AssemblyResolve
有一个订阅它的处理程序。订阅此事件的ResolveEventHandler
已添加到我的代码的上游(据我所知,System.AppDomain
有自己的Private Method
订阅了该事件... ...是否可以删除这个事件的所有处理程序,以便我可以添加自己的处理程序并确保它是只有一个?
基本上我正在尝试这样做:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ClassX.MethodX
但是我不知道这个例子中有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
现在我正在尝试删除它,就像这样,因为它不是Public方法:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly")
但是这给出了一个编译错误:“AddressOf参数必须是方法的名称”。所以我不确定如何在这里指定非公共方法
答案 0 :(得分:1)
来自原始评论:
Here's一个关于从没有委托签名的事件中移除委托的主题......非常方便,但最后海报说明了
“看起来AppDomain.CurrentDomain.AssemblyResolve根本不支持删除事件,所以我发布的代码不起作用。”
甚至.NET抱怨事件System.AppDomain.AssemblyResolve
只能显示在+=
或-=
的左侧(+=/-=
运算符是C#AddHandler/RemoveHandler
)..所以它看起来像'不':/
此外,在您进行编辑后,您无法执行以下操作:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly")
因为AddressOf
关键字是一个运营商关键字,类似于作为运营商的+
或-
,AddressOf
对所提供的程序进行操作,且必须是它可以在编译时推断出的过程名称。并且GetMethod
函数返回MethodInfo
类型而不是已知的函数地址。
然而,一切都没有丢失!
AddHandler
和RemoveHandler
函数实际上要求传递Object
和Delegate
(AddressOf
汇编成Delegate
使用时),所以你不需要AddressOf
做你想做的事,你需要一个Delegate
。
为此,我们可以使用{i>做取MethodInfo
个对象的CreateDelegate
方法。应该注意的是,由于您尝试访问私有方法,因此您需要指定Reflection.BindingFlags.Instance
和Reflection.BindFlags.NonPublic
的{{3}}(我说and
但是你'我会对它们进行按位Or
,例如:
GetType(Reflection.Assembly).GetMethod("ResolveAssembly", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
所以在此调用CreateDelegate
将为我们提供以下代码
[Delegate].CreateDelegate(GetType(Reflection.Assembly), GetType(Reflection.Assembly).GetMethod("ResolveAssembly", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic))
但这相当冗长,所以让我们分解一下:
Dim type As Type = GetType(Reflection.Assembly)
Dim mi As Reflection.MethodInfo = type.GetMethod("ResolveAssembly", (Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic))
现在,我们只需通过以下内容致电RemoveHandler
上的AppDomain.CurrentDomain.AssemblyResolve
:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, [Delegate].CreateDelegate(type, mi)
除AppDomain.CurrentDomain.AssemblyResolve
期望委托/事件签名匹配,因此我们需要将创建的委托转换为适当的类型:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, CType([Delegate].CreateDelegate(type, mi), System.ResolveEventHandler)
现在,您可以通过事件处理程序的反射删除私有方法。
警告!! 虽然这段代码将编译并运行,但我不保证它的有效性或准确性,因为你正在使用帧和堆栈指针(本质上),所以当它可能运行时它可能工作,它也可能产生小猫..所以要小心。
希望能有所帮助!