EventInfoクラスには、直接イベントを発行するメソッドは用意されていません。 そのためイベント発行時の動作と同等の処理を独自に記述する必要があります。 EventInfoクラスからは以下のような手順をとることでイベントの発行を行うことができます。
- イベントハンドラのデリゲートを格納しているフィールドのFieldInfoを取得する
- 取得したFieldInfoからイベントハンドラを格納しているMulticastDelegateを取得する
- MulticastDelegate.GetInvocationListメソッドを使ってイベントハンドラとして割り当てられているメソッドのリスト(MethodInfoの配列)を取得する
- 取得したMethodInfoひとつずつに対してメソッドの呼び出しを行う
C#とVBではイベントハンドラを格納しているフィールド名が異なる点に注意が必要です。 例えばイベント名がClick
の場合、C#ではフィールドClick
、VBではフィールドClickEvent
にイベントハンドラが格納されます。
上記の処理を具体的に実装すると次のようになります。
EventInfoを使ってイベントの発行を行う
Imports System
Imports System.Reflection
Class C
Public Event E As EventHandler(Of EventArgs)
End Class
Class Sample
Shared Sub Handler1(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("Handler1")
End Sub
Shared Sub Handler2(ByVal sender As Object, ByVal e As EventArgs)
Console.WriteLine("Handler2")
End Sub
Shared Sub Main()
Dim inst As New C()
' イベントEにハンドラを割り当てる
AddHandler inst.E, AddressOf Handler1
AddHandler inst.E, AddressOf Handler2
' イベントEのEventInfoを取得する
Dim ev As EventInfo = inst.GetType().GetEvent("E")
' EventInfoを使ってイベントを発行する
Raise(inst, ev, EventArgs.Empty)
End Sub
Shared Sub Raise(Of TEventArgs)(ByVal sender As Object, ByVal ev As EventInfo, ByVal e As TEventArgs)
Dim f As FieldInfo = sender.GetType().GetField(ev.Name + "Event", BindingFlags.Instance Or BindingFlags.NonPublic)
Dim handler As MulticastDelegate = DirectCast(f.GetValue(sender), MulticastDelegate)
If handler Is Nothing Then Return
For Each h As [Delegate] In handler.GetInvocationList()
h.Method.Invoke(h.Target, New Object() {sender, e})
Next
End Sub
End Class
実行結果
Handler1 Handler2
MulticastDelegate.GetInvocationListメソッドについてはデリゲートの機能 §.呼び出されるメソッド・インスタンスの取得 (Method, Target, GetInvocationList)で解説しています。