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