EventInfo.GetRaiseMethod 是否可以返回一个实例,当从 VB.NET 在 CIL 上使用时



在线程EventInfo.GetRaiseMethod()总是 null 中,著名专家 Hans Passant 给出了一个答案,他解释说,如果 CIL 来自 VB.NET(或 F# 或 C++/CLI(,而不是 C#,那么方法EventInfo.GetRaiseMethod将返回一些东西(即一个实例,一个不nullNothing的引用(。

不是很熟悉 VB.NET,我尝试用Event编写一些 VB.NET 代码,试图获得一个GetRaiseMethod返回一些东西的情况。

我尝试了AddHandler语句,但我也尝试了Handles子句。前者似乎只在运行时订阅事件(就像在 C# 中使用 += 运算符一样,我认为?(,但后者似乎更有希望,因为它在编译时声明关系(?(。

我仍然没有成功使用GetRaiseMethod,它返回Nothing(null(。如何创建一个示例来证明GetRaiseMethod可以不平凡地返回来自 VB.NET 的代码?

好吧,也许我一开始就不应该创建一个新线程。但是,我根据汉斯·帕桑特的建议(在另一个线程中(制作了这个线程。

Passant对我上面问题的直接评论非常有帮助。下面是一段说明这种情况的代码:

Imports System
Imports System.Reflection
Module M
    Sub Main()
        AddHandler C1.Bang, AddressOf SomeAction
        C1.Test()
        AddHandler C2.Boom, AddressOf SomeAction
        C2.Test()
        ' Check which GetRaiseMethod find something
        Dim bangRaiseAccessor As MethodInfo = GetType(C1).GetEvent("Bang").GetRaiseMethod(True)
        Dim boomRaiseAccessor As MethodInfo = GetType(C2).GetEvent("Boom").GetRaiseMethod(True)
        Console.WriteLine("M: GetRaiseMethod(True) for C1.Bang: {0}",
                          If(bangRaiseAccessor, DirectCast("<none>", Object))
                          )
        Console.WriteLine("M: GetRaiseMethod(True) for C2.Boom: {0}",
                          If(boomRaiseAccessor, DirectCast("<none>", Object))
                          )
    End Sub
    Private Sub SomeAction()
        Console.WriteLine("M: Inside 'SomeAction'.")
    End Sub
End Module
Class C1
    ' auto-event; backing delegate type, backing field and accessor methods are compiler-generated
    Shared Event Bang()
    Private Shared Sub OnBang() Handles Me.Bang
        Console.WriteLine("C1: Inside 'OnBang'.")
    End Sub
    Shared Sub Test()
        Console.WriteLine("C1: Test firing event Bang.")
        RaiseEvent Bang()
        Console.WriteLine("C1: Test finished.")
    End Sub
End Class
Class C2
    Shared Custom Event Boom As Action
        AddHandler(value As Action)
            Console.WriteLine("C2: Inside custom AddHandler accessor, 'value' contains '{0}'.",
                              If(value = Nothing, "<none>", value.Method.ToString())
                              )
            ' TODO: use parameter, for example aggregate "value" in field with delegate combination
        End AddHandler
        RemoveHandler(value As Action)
            Console.WriteLine("C2: Inside custom RemoveHandler accessor, 'value' contains '{0}'.",
                              If(value = Nothing, "<none>", value.Method.ToString())
                              )
            ' TODO: use parameter, for example subtract "value" from field with delegate removal
        End RemoveHandler
        RaiseEvent()
            Console.WriteLine("C2: Inside custom RaiseEvent accessor.")
        End RaiseEvent
    End Event
    Private Shared Sub OnBoom() Handles Me.Boom
        Console.WriteLine("C2: Inside 'OnBoom'.")
    End Sub
    Shared Sub Test()
        Console.WriteLine("C2: Test firing event Boom.")
        RaiseEvent Boom()
        Console.WriteLine("C2: Test finished.")
    End Sub
End Class

一个得到输出:

C1:试射事件砰。C1:在"OnBang"内部。男:在"某行动"里面。C1:测试完成。C2:在自定义 AddHandler 访问器中,"value"包含"Void OnBoom(("。C2:在自定义 AddHandler 访问器中,"value"包含"Void SomeAction(("。C2:试射事件 动臂。C2:在自定义 RaiseEvent 访问器中。C2:测试完成。M: GetRaiseMethod(True( for C1.砰:M: GetRaiseMethod(True( for C2.动臂:虚空raise_Boom((

结论:

  • "自动"Event将没有 raise 访问器方法,GetRaiseMethod将返回Nothing
  • Custom Event需要一个raise 访问器方法RaiseEvent(...)GetRaiseMethod(True)返回它的反射表示(MethodInfo
  • 订阅事件(Custom或不订阅(发生在运行时,无论您是否使用语法AddHandler C1.Bang, AddressOf SomeAction订阅(在这种情况下,订阅发生在到达此语句时,当然(,或者您使用语法Private Shared Sub OnBang() Handles Me.Bang订阅(在这种情况下,订阅发生得更早,在任何AddHandler语句运行之前,当然在使用该Event Bang之前
  • (

相关内容

  • 没有找到相关文章

最新更新