如何在运行时使用相同的事件附加到不同的类?

时间:2016-05-14 15:27:21

标签: vb.net events event-handling late-binding

鉴于两个具有相同事件的类,我希望能够使用一个名称来引用它们。类似于以下内容:

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不是'对象'的事件。

看起来属性和方法很好,但事件不是。在这种情况下如何处理事件?

2 个答案:

答案 0 :(得分:2)

该代码段与此问题不符。它有一个奇怪的错误,类中的事件未声明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语句添加后期绑定支持。我不知道他们决定这个的确切原因,只能猜测。没有技术原因无法添加,只需要编译器生成反射代码。一种可能的解释是他们认为它太贵了。另一个原因是他们认为当方法签名不匹配时难以解释时会引发运行时异常。我最喜欢最后一个,它们非常难看。

你必须使用Reflection来获得你想要的东西。使用obj1.GetType()。GetEvent(“event1”)获取EventInfo,使用Get / AddMethod()添加事件处理程序。

Fwiw,C#语言在其动态关键字实现中支持这一点。也许你可以通过asking for the feature在他们的耳边放一个小虫。如果以前要求的话,不知道。

答案 1 :(得分:1)

您可以为事件定义接口并在类中实现它,然后您可以通过接口引用订阅此事件。见下文:

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