VB.NET中的多态性通过Late Binding不允许使用事件,解决方法?

时间:2009-08-30 14:44:28

标签: vb.net oop polymorphism

我正在开发一个与一系列USB传感器对话的应用程序。我创建了一个使用名为Sensor的类的基本实现。该类包含允许与传感器交互的事件和方法(还涉及一个线程化的任务处理器,但我将用一个简单的例子)。

我的问题是这个简单的概念验证示例工作正常,但现在我需要扩展应用程序以支持整个传感器系列。为此,我创建了一个包含所有适当方法和事件的BaseSensor类,然后我创建了多个子类,例如SensorA,SensorB和SensorC,它们都是固有的BaseSensor。

这似乎是多态的一个很好的应用,所以我在BaseSensor上创建了一个名为Initialize的共享函数,它执行初始USB通信并根据传感器类型(SensorA,SensorB,SensorC)返回正确的对象。这工作正常,但似乎我找不到正确声明具有事件的对象的方法。请参阅我的deliema的示例代码。

尝试1:

Public Class Form1
    Dim WithEvents oBaseClass As BaseClass
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        oBaseClass = New ExtendedClass
        oBaseClass.Test() 'This doesn't work because the object was type casted.
    End Sub

    Private Sub TestEventHdlr() Handles oBaseClass.TestEvent
        MsgBox("Event Fired")
    End Sub
End Class

Public Class BaseClass
    Public Event TestEvent()
End Class

Public Class ExtendedClass
    Inherits BaseClass
    Public Sub Test()
        MsgBox("Test")
    End Sub
End Class

尝试2:

Public Class Form1
    Dim WithEvents oBaseClass 'This doesn't work.
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        oBaseClass = New ExtendedClass
        oBaseClass.Test()
    End Sub

    Private Sub TestEventHdlr() Handles oBaseClass.TestEvent
        MsgBox("Event Fired")
    End Sub
End Class

Public Class BaseClass
    Public Event TestEvent()
End Class

Public Class ExtendedClass
    Inherits BaseClass
    Public Sub Test()
        MsgBox("Test")
    End Sub
End Class

我在这里遗漏了一些东西。我该怎么办?

4 个答案:

答案 0 :(得分:3)

WithEvents不能晚绑定。您需要使用类型声明您的字段。如果在这种情况下使用的所有对象都来自一个共同的基础,那么你将在放弃后期绑定方面做出巨大贡献。必要时进行转换,并声明虚拟(可覆盖)方法以实现您的多态性。

Public Class Form1
    Dim WithEvents oBaseClass As BaseClass 'Early bound'

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        oBaseClass = New ExtendedClass
        DirectCast(oBaseClass, ExtendedClass).Test() 'Casting to call a method'
    End Sub

    Private Sub TestEventHdlr() Handles oBaseClass.TestEvent
        MsgBox("Event Fired")
    End Sub
End Class

Public Class BaseClass
    Public Event TestEvent()
End Class

Public Class ExtendedClass
    Inherits BaseClass
    Public Sub Test()
        MsgBox("Test")
    End Sub
End Class

答案 1 :(得分:0)

这就是你要找的东西吗?

Public Class Form1
    Private WithEvents oBaseClass As ExtendedClass

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        oBaseClass = New ExtendedClass
        oBaseClass.Test()
    End Sub

    Private Sub TestEventHdlr() Handles oBaseClass.TestEvent
        MsgBox("Event Fired")
    End Sub
End Class

Public Class BaseClass
    Public Event TestEvent()
    Friend Sub raiseTestEvent()
        RaiseEvent TestEvent()
    End Sub
End Class

Public Class ExtendedClass
    Inherits BaseClass
    Public Sub Test()
        MsgBox("Test")
        raiseTestEvent()
    End Sub
End Class

如果没有,您需要创建一个接口并在表单中声明它并在form_load中设置相应的类

答案 2 :(得分:0)

稍微调整以提升事件,以防你想要一个例子,稍微改变一下事件以提供一点点不同的方法。

Public Class Form1

    Dim oBaseClass As BaseClass 'Early bound'
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        oBaseClass = New ExtendedClass
        If TypeOf oBaseClass Is BaseClass Then
            AddHandler DirectCast(oBaseClass, BaseClass).TestEvent, AddressOf TestEventHdlr
        End If
        oBaseClass.Test()
    End Sub
    Private Sub TestEventHdlr()
        MsgBox("Event Fired")
    End Sub
End Class
Public Class BaseClass
    Public Event TestEvent()
    Public Overridable Sub Test()
        RaiseEvent TestEvent()
    End Sub
End Class
Public Class ExtendedClass
    Inherits BaseClass
    Public Overrides Sub Test()
        MyBase.Test()
        MsgBox("Test")
    End Sub
End Class

答案 3 :(得分:0)

根据您要建模的行为类型,您可能需要考虑使用Interfaces而不是Inheritence或两者的混合。不是拥有定义事件的基础对象,而是基于接口定义行为或函数,并在ExtendedClass的等效项中实现它们

这让我很烦恼但是它迫使我了解它们,因为你可以为每个对象实现多种接口类型,它最终非常灵活。

一个提示:首先考虑界面内容。虽然VS自动为您插入方法/属性存根,但如果您稍后更改接口的定义,则需要手动更新实现。

西蒙