我需要编写一个通用函数,用于删除Sub和Func的所有事件处理程序(我需要通用函数才能与子例程和函数一起正常工作)。
...问题是我不知道该怎么做,我看到了声明代表的例子,但这并不像我精确的那样通用。
我读过这篇关于 CodeProject 的文章,但代码是 C# 我什么都看不懂:http: //www.codeproject.com/Articles/103542/Removing-Event-Handlers-using-Reflection
这是我唯一能做的:
Public Class Form1
' Call the function to remove all the handlers of "MySub"
' Clear_Handles(Of MySub)
Private Function Clear_Handles(Of T)(ByVal MethodName As T)
' Code to remove all handlers(of "MethodName")
End Function
Private Sub MySub() Handles event1, event2, event3
' bla bla bla
End Sub
End Class
感谢阅读。
更新
我试图将上面的代码转换为VB只是为了尝试但我不能使用它,我不知道如何使用它,这就是我所做的:
Public Class Form1
Private Sub MySub() Handles Button1.Click, Button2.click
' Do nothing
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Attempting to remove "Button1.Click" and "Button2.click" events of "MySub()"
PSLib.cEventHelper.RemoveAllEventHandlers(MySub)
End Sub
End Class
...这是翻译后的代码,我不知道它是否有效,因为我不知道如何使用这些方法:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.IO
Imports System.Management
Imports System.Reflection
Imports System.Text
Namespace PSLib
'--------------------------------------------------------------------------------
Public NotInheritable Class cEventHelper
Private Sub New()
End Sub
Shared dicEventFieldInfos As New Dictionary(Of Type, List(Of FieldInfo))()
Private Shared ReadOnly Property AllBindings() As BindingFlags
Get
Return BindingFlags.IgnoreCase Or BindingFlags.[Public] Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.[Static]
End Get
End Property
'--------------------------------------------------------------------------------
Private Shared Function GetTypeEventFields(t As Type) As List(Of FieldInfo)
If dicEventFieldInfos.ContainsKey(t) Then
Return dicEventFieldInfos(t)
End If
Dim lst As New List(Of FieldInfo)()
BuildEventFields(t, lst)
dicEventFieldInfos.Add(t, lst)
Return lst
End Function
'--------------------------------------------------------------------------------
Private Shared Sub BuildEventFields(t As Type, lst As List(Of FieldInfo))
' Type.GetEvent(s) gets all Events for the type AND it's ancestors
' Type.GetField(s) gets only Fields for the exact type.
' (BindingFlags.FlattenHierarchy only works on PROTECTED & PUBLIC
' doesn't work because Fieds are PRIVATE)
' NEW version of this routine uses .GetEvents and then uses .DeclaringType
' to get the correct ancestor type so that we can get the FieldInfo.
For Each ei As EventInfo In t.GetEvents(AllBindings)
Dim dt As Type = ei.DeclaringType
Dim fi As FieldInfo = dt.GetField(ei.Name, AllBindings)
If fi IsNot Nothing Then
lst.Add(fi)
End If
Next
End Sub
'--------------------------------------------------------------------------------
Private Shared Function GetStaticEventHandlerList(t As Type, obj As Object) As EventHandlerList
Dim mi As MethodInfo = t.GetMethod("get_Events", AllBindings)
Return DirectCast(mi.Invoke(obj, New Object() {}), EventHandlerList)
End Function
'--------------------------------------------------------------------------------
Public Shared Sub RemoveAllEventHandlers(obj As Object)
RemoveEventHandler(obj, "")
End Sub
'--------------------------------------------------------------------------------
Public Shared Sub RemoveEventHandler(obj As Object, EventName As String)
If obj Is Nothing Then
Return
End If
Dim t As Type = obj.[GetType]()
Dim event_fields As List(Of FieldInfo) = GetTypeEventFields(t)
Dim static_event_handlers As EventHandlerList = Nothing
For Each fi As FieldInfo In event_fields
If EventName <> "" AndAlso String.Compare(EventName, fi.Name, True) <> 0 Then
Continue For
End If
' After hours and hours of research and trial and error, it turns out that
' STATIC Events have to be treated differently from INSTANCE Events...
If fi.IsStatic Then
' STATIC EVENT
If static_event_handlers Is Nothing Then
static_event_handlers = GetStaticEventHandlerList(t, obj)
End If
Dim idx As Object = fi.GetValue(obj)
Dim eh As [Delegate] = static_event_handlers(idx)
If eh Is Nothing Then
Continue For
End If
Dim dels As [Delegate]() = eh.GetInvocationList()
If dels Is Nothing Then
Continue For
End If
Dim ei As EventInfo = t.GetEvent(fi.Name, AllBindings)
For Each del As [Delegate] In dels
ei.RemoveEventHandler(obj, del)
Next
Else
' INSTANCE EVENT
Dim ei As EventInfo = t.GetEvent(fi.Name, AllBindings)
If ei IsNot Nothing Then
Dim val As Object = fi.GetValue(obj)
Dim mdel As [Delegate] = TryCast(val, [Delegate])
If mdel IsNot Nothing Then
For Each del As [Delegate] In mdel.GetInvocationList()
ei.RemoveEventHandler(obj, del)
Next
End If
End If
End If
Next
End Sub
End Class
End Namespace
更新
这是我会做的一个例子:
private sub form1_shown() handles me.shown
RemoveAll_EventHandlers(of MyMethod)
' So it will remove: button1.click, button2.click, button3.click
end sub
Private sub MyMethod() handles button1.click, button2.click, button3.click
' Nothing to do here. . .
end sub
public sub RemoveAll_EventHandlers(of T)(byval MethodName as T)
For each evt as event in MethodName : removehandler control.event, addres of(T)
end sub
更新:
你想象的另一个例子......:
Private Sub RemoveAll_EventHandlers(Of T)(ByVal MethodName As T)
For Each ctrl As Control In Me.Controls
For Each evt As EventHandler In Control
RemoveHandler ctrl.evt, addresof(T)
Next
Next
End Sub
private sub form1_shown() handles me.shown
RemoveAll_EventHandlers(of MyMethod)
' So it will remove: button1.click, button2.click, button3.click
end sub
Private sub MyMethod() handles button1.click, button2.click, button3.click
' Nothing to do here. . .
end sub