views:

411

answers:

4

Hello,

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?

A: 

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

Fredou
A: 

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
Snarfblam
Ahha, this is exactly what I was looking for! Thank you so much!I only picked up VB.Net a few months ago and I've learned teaching yourself leaves some small gaps in your skillset that must be filled in, via painful hours of reading msdn, and as a last resort via StackOverflow.
Andrew Robinson
You might want to read some good practices articles. I can't name any offhand, but it helps a lot to pick up the good habits early.
Snarfblam
Is this not a good practice? I'll have to go out and read some more.
Andrew Robinson
Unless there is a specific reason you want duck typing (http://en.wikipedia.org/wiki/Duck_typing) it is best to ensure option strict (http://support.microsoft.com/kb/311329) is enabled to avoid late binding all together. There are a number of small headaches you'll avoid.
Snarfblam
A: 

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
omantn
A: 

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

Simon