如何在运行时附加到具有相同事件的不同类



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

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

相关内容

  • 没有找到相关文章

最新更新