给定两个具有相同事件的类,我希望能够使用一个名称来引用它们。类似于以下内容:
Public Class myclass1
Public event1()
End Class
Public Class myclass2
Public event1()
End Class
在这里,我希望能够在运行时确定使用哪个类:
Sub somefunction(select as integer)
Dim voidclass
if select = 1 then
voidclass = myclass1
else
voidclass = myclass2
end if
AddHandler voidclass.event1, AddressOf eventhappened
End Sub
Sub eventhappened()
msgbox("Event occured")
End Sub
显然,对于这个例子可能有更好的方法,但让我们假设类book1
已经存在,并且我的任务是创建book2
,只修改somefunction
,而不修改book1
本身。
上面的示例应该会导致错误event1
不是"Object"的事件。
属性和方法似乎对此很好,但事件则不然。在这种情况下,我该如何处理事件?
这个片段与问题不太匹配。它有一个奇怪的错误,类中的事件没有声明为Shared
,因此代码必须使用正确的对象引用。不是类型名称。也许答案很简单:
Private obj1 As myclass1
Private obj2 As myclass2
Sub somefunction(select as integer)
If select = 1 Then
AddHandler obj1.event1, AddressOf eventhappened
Else
AddHandler obj2.event1, AddressOf eventhappened
End If
End Sub
但据推测,真正的问题是相同的场景,但现在变量声明为:
Private obj1, obj2
未打字,因此为Object
。是的,VB.NET不支持此功能。与VB.NET中的大多数怪癖一样,这背后也有其历史。VB从不支持事件的显式后期绑定,只支持方法和属性。传统版本中的方案非常古怪。您必须使用WithEvents
关键字声明变量,并为事件处理程序选择一个特定的名称。换句话说:
Dim WithEvents obj1
Sub obj1_somethinghappened
'' handles the event1 event for obj1
End Sub
或者换一种说法,所有的活动都是迟到的。这个方案没有被移植到VB.NET中,它有太多的实际问题。WithEvents
仍然存在,但现在需要在方法声明中使用Handles
关键字。这不是你想让它做的。
VB.NET设计器有意不向AddHandler
语句添加后期绑定支持。我不知道他们决定这样做的确切原因,只能猜测。没有技术原因不能添加它,它只需要编译器生成反射代码。一种可能的解释是他们认为它太贵了。另一个原因是,他们认为当方法签名不匹配时引发的运行时异常太难解释。我最喜欢最后一个,它们很丑。
你必须使用"反射"才能得到你想要的东西。使用obj1.GetType().GetEvent("event1")获取EventInfo,使用其get/AddMethod()添加事件处理程序。
Fwiw,C#语言在其动态关键字实现中确实支持这一点。也许你可以通过询问功能来让他们听到一个bug。不知道这是不是以前要求的。
您可以为事件定义一个接口并在类中实现它,然后您可以通过接口引用订阅此事件。见下文:
Public Interface INotifier
Event SomethingHappened()
End Interface
Public Class Class1
Implements INotifier
Public Event SomethingHappened() Implements INotifier.SomethingHappened
End Class
Public Class Class2
Implements INotifier
Public Event SomethingHappened() Implements INotifier.SomethingHappened
End Class
Module Module1
Dim notifiers As List(Of INotifier) = New List(Of INotifier) From
{
New Class1(),
New Class2()
}
Sub Main()
SubscribeToEventHandler(0)
End Sub
Private Sub SubscribeToEventHandler(ByVal index As Integer)
Dim notifier As INotifier = notifiers(index)
AddHandler notifier.SomethingHappened, AddressOf EventHandler
End Sub
Private Sub EventHandler()
End Sub
End Module