是否可以删除您的 class 未添加的 VB.NET EventHandler?
Is it possible to Remove a VB.NET EventHandler that your class didn't Add?
在我的 VB.NET 应用程序中,事件 AppDomain.CurrentDomain.AssemblyResolve
有一个处理程序订阅了它。订阅此事件的 ResolveEventHandler
是在我的代码上游添加的(据我所知,System.AppDomain
有自己的 Private Method
订阅了该事件)...是否可以删除此事件的所有处理程序,以便我可以添加自己的处理程序并确保它是 唯一的一个?
基本上我正在尝试这样做:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ClassX.MethodX
但我不知道这个例子中的ClassX
或MethodX
是什么,因为我还没有为这个事件添加处理程序,而这个处理程序是由上游代码添加的。我正在使用这里描述的方法来检查是否有任何处理程序是订阅事件:
编辑:我能够在调试时使用立即 Window 找出订阅事件的方法。
? 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 parameter must be the name of a method"。所以我不确定如何在此处指定非Public方法
来自原评论:
Here's 一个关于从您没有代表签名的事件中删除代表的主题......非常方便,但最后发帖人说
"It looks like AppDomain.CurrentDomain.AssemblyResolve doesn't support removal of events at all so the code I posted won't work."
甚至 .NET 也抱怨事件 System.AppDomain.AssemblyResolve
只能出现在 +=
或 -=
的左侧(+=/-=
运算符是 C# AddHandler/RemoveHandler
) .. 所以它看起来像 'no' :/
此外,在您编辑后,您无法执行以下操作的原因:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly")
是因为AddressOf
keyword is an operator keyword, similar to a +
or -
being an operator, the AddressOf
operates on the procedure given and it must be a procedure name it can deduce at compile time. And the GetMethod
function returns a MethodInfo
类型而不是已知的函数地址。
然而万事俱备!
AddHandler
and RemoveHandler
functions actually call for an Object
and Delegate
to be passed in (AddressOf
gets compiled into a Delegate
when used), so you don't need the AddressOf
to do what you want, you need a Delegate
.
要做到这一点,我们可以使用 Reflection.BindingFlags.Instance
和 Reflection.BindFlags.NonPublic
的 CreateDelegate
method which does take a MethodInfo
object. It should be noted that since you're trying to access private methods, you'll need to specify the BindFlags
(我说 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))
现在我们可以通过以下方式简单地调用 AppDomain.CurrentDomain.AssemblyResolve
上的 RemoveHandler
:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, [Delegate].CreateDelegate(type, mi)
Except AppDomain.CurrentDomain.AssemblyResolve
期望 delegate/event 签名匹配,因此我们需要将创建的委托转换为适当的类型:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, CType([Delegate].CreateDelegate(type, mi), System.ResolveEventHandler)
您现在可以通过事件处理程序的反射删除私有方法。
警告!!
虽然这段代码会编译 运行,但我不保证它的有效性或准确性,因为你正在处理帧和堆栈指针(本质上),所以虽然它 可能 运行 它 可能 有效,它也 可能 产生小猫..所以要小心。
希望能帮到你!
在我的 VB.NET 应用程序中,事件 AppDomain.CurrentDomain.AssemblyResolve
有一个处理程序订阅了它。订阅此事件的 ResolveEventHandler
是在我的代码上游添加的(据我所知,System.AppDomain
有自己的 Private Method
订阅了该事件)...是否可以删除此事件的所有处理程序,以便我可以添加自己的处理程序并确保它是 唯一的一个?
基本上我正在尝试这样做:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf ClassX.MethodX
但我不知道这个例子中的ClassX
或MethodX
是什么,因为我还没有为这个事件添加处理程序,而这个处理程序是由上游代码添加的。我正在使用这里描述的方法来检查是否有任何处理程序是订阅事件:
编辑:我能够在调试时使用立即 Window 找出订阅事件的方法。
? 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 parameter must be the name of a method"。所以我不确定如何在此处指定非Public方法
来自原评论:
Here's 一个关于从您没有代表签名的事件中删除代表的主题......非常方便,但最后发帖人说
"It looks like AppDomain.CurrentDomain.AssemblyResolve doesn't support removal of events at all so the code I posted won't work."
甚至 .NET 也抱怨事件 System.AppDomain.AssemblyResolve
只能出现在 +=
或 -=
的左侧(+=/-=
运算符是 C# AddHandler/RemoveHandler
) .. 所以它看起来像 'no' :/
此外,在您编辑后,您无法执行以下操作的原因:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf GetType(Reflection.Assembly).GetMethod("ResolveAssembly")
是因为AddressOf
keyword is an operator keyword, similar to a +
or -
being an operator, the AddressOf
operates on the procedure given and it must be a procedure name it can deduce at compile time. And the GetMethod
function returns a MethodInfo
类型而不是已知的函数地址。
然而万事俱备!
AddHandler
and RemoveHandler
functions actually call for an Object
and Delegate
to be passed in (AddressOf
gets compiled into a Delegate
when used), so you don't need the AddressOf
to do what you want, you need a Delegate
.
要做到这一点,我们可以使用 Reflection.BindingFlags.Instance
和 Reflection.BindFlags.NonPublic
的 CreateDelegate
method which does take a MethodInfo
object. It should be noted that since you're trying to access private methods, you'll need to specify the BindFlags
(我说 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))
现在我们可以通过以下方式简单地调用 AppDomain.CurrentDomain.AssemblyResolve
上的 RemoveHandler
:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, [Delegate].CreateDelegate(type, mi)
Except AppDomain.CurrentDomain.AssemblyResolve
期望 delegate/event 签名匹配,因此我们需要将创建的委托转换为适当的类型:
RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, CType([Delegate].CreateDelegate(type, mi), System.ResolveEventHandler)
您现在可以通过事件处理程序的反射删除私有方法。
警告!! 虽然这段代码会编译 运行,但我不保证它的有效性或准确性,因为你正在处理帧和堆栈指针(本质上),所以虽然它 可能 运行 它 可能 有效,它也 可能 产生小猫..所以要小心。
希望能帮到你!