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