2015-10-14 60 views
0

在线程EventInfo.GetRaiseMethod() always null,有an answer由著名专家汉斯帕桑特,他解释说,如果CIL来自VB.NET(或F#或C++/CLI),而不是C#,那么method EventInfo.GetRaiseMethod将返回一些东西(例如,一个参考不是nullNothing)。当在VB.NET中使用CIL时,EventInfo.GetRaiseMethod是否可以返回一个实例?

对VB.NET不是很熟悉,我试着写一些VB.NET代码与Event,试图获得一个案例,使GetRaiseMethod返回的东西。

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

我还没有成功与GetRaiseMethod,它返回Nothing(空)。 如何创建一个示例以显示GetRaiseMethod对于来自VB.NET的代码可以非平凡地返回?

+4

您没有发布您的代码。感谢downvote顺便说一句,可爱,总是很高兴提醒你,没有写出正确的代码是我的问题。使用Event声明中的Custom关键字,以便您可以声明RaiseEvent访问器。使用BindingFlags.NonPublic | BindingFlags.Instance在GetRaiseMethod()调用中。 –

回答

0

好吧,也许我不应该在第一个地方创建一个新的线程。但是,我在Hans Passant的建议(在另一个线程中)做了这个线索。

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: Test firing event Bang. 
C1: Inside 'OnBang'. 
M: Inside 'SomeAction'. 
C1: Test finished. 
C2: Inside custom AddHandler accessor, 'value' contains 'Void OnBoom()'. 
C2: Inside custom AddHandler accessor, 'value' contains 'Void SomeAction()'. 
C2: Test firing event Boom. 
C2: Inside custom RaiseEvent accessor. 
C2: Test finished. 
M: GetRaiseMethod(True) for C1.Bang: 
M: GetRaiseMethod(True) for C2.Boom: Void raise_Boom()

结论:

  • “自动” Event不会有加薪访问器方法,并GetRaiseMethod将返回Nothing
  • 一个Custom Event需要一个加薪访问方法RaiseEvent(...),和GetRaiseMethod(True)返回它的反射表示(MethodInfo
  • 订阅事件(Custom与否)发生在运行时,无论您订阅与语法AddHandler C1.Bang, AddressOf SomeAction(在这种情况下,达到此语句时的认购情况,当然),或您订阅的语法Private Shared Sub OnBang() Handles Me.Bang(在这种情况下,认购早期发生的,任何AddHandler语句运行之前,肯定任何使用Event Bang之前)
相关问题