问题
I'm working on developing an application that talks to a family of USB sensors. I've created a basic implementation that utilizes a class called Sensor. The class contains events and methods that allow for interaction with the sensor (there is also a threaded task processor involved but I'll go with a simple example).
My issue is that this simple proof of concept example works fine but now I need to expand the application to support the whole family of sensors. To do this I've created a BaseSensor class with all the appropriate methods and events and then I've created multiple subclasses such as SensorA, SensorB, and SensorC that all inherent BaseSensor.
This seemed like a good application of polymorphism so I've created a Shared function on BaseSensor called Initialize that does an initial USB communication and returns the correct object depending on the sensor type (SensorA, SensorB, SensorC). This works fine however it seems I can not find a way to correctly declare the object With Events. See the sample code for my deliema.
Attempt 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
Attempt 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
I'm missing something here. How should I proceed?
回答1:
WithEvents can not be late bound. You need to declare your field with a type. If all objects used in this scenario derive from a common base, you will be doing yourself a huge favor in ditching late binding. Cast when necessary, and declare virtual (overridable) methods to implement your polymorphism.
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
回答2:
is this what your looking for?
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
if not, you need to create an interface and declare it in your form and setting the corresponding class to it in the form_load
回答3:
Adjusted slightly to raise the event in case you wanted an example of that, altered the event a bit as well to provide a bit different approach.
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
回答4:
Depending on the types of behaviour you're looking to model, you might want to consider using Interfaces instead of Inheritence or a mixture of both. Rather than having a base object that defines the event, define behaviours or functions based around interfaces and implement those in the equivilent of your ExtendedClass
This annoyed me a lot too but it kind of forced me to learn about them and as you can implement multiple interface types per object it's ultimately very flexible.
One tip though: think about interface content first. Although VS auto inserts method/property stubs for you, if you later change the definition of the interface it's a manual effort to update the implementations.
Simon
来源:https://stackoverflow.com/questions/1354032/polymorphism-in-vb-net-via-late-binding-disallows-with-events-workaround