Полиморфизм в VB.NET через позднюю привязку запрещает использование событий, обходной путь? - PullRequest
2 голосов
/ 30 августа 2009

Я работаю над разработкой приложения, которое взаимодействует с семейством USB-датчиков. Я создал базовую реализацию, которая использует класс Sensor. Класс содержит события и методы, которые позволяют взаимодействовать с датчиком (также задействован многопоточный процессор задач, но я остановлюсь на простом примере).

Моя проблема в том, что этот простой пример доказательства концепции работает нормально, но теперь мне нужно расширить приложение для поддержки всего семейства датчиков. Для этого я создал класс BaseSensor со всеми соответствующими методами и событиями, а затем создал несколько подклассов, таких как SensorA, SensorB и SensorC, которым присущ BaseSensor.

Это выглядело как хорошее применение полиморфизма, поэтому я создал в BaseSensor функцию Shared, которая называется 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 ]

3 голосов
/ 30 августа 2009

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
0 голосов
/ 04 сентября 2009

В зависимости от типов поведения, которые вы хотите моделировать, вы можете рассмотреть возможность использования интерфейсов вместо наследования или их комбинации. Вместо того, чтобы иметь базовый объект, который определяет событие, определите поведение или функции, основанные на интерфейсах, и реализуйте их в эквиваленте вашего ExtendedClass

Это меня тоже сильно раздражало, но отчасти заставило меня узнать о них, и, поскольку вы можете реализовать несколько типов интерфейсов для каждого объекта, это в конечном итоге очень гибко.

Один совет: сначала подумайте о содержимом интерфейса. Несмотря на то, что VS автоматически вставляет заглушки метода / свойства для вас, если позже вы измените определение интерфейса, это будет попытка обновить реализации вручную.

Simon

0 голосов
/ 02 сентября 2009

Немного откорректировано, чтобы вызвать событие в случае, если вам нужен пример этого, также немного изменило событие, чтобы обеспечить немного другой подход.

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
0 голосов
/ 30 августа 2009

это то, что вы ищете?

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

если нет, вам нужно создать интерфейс и объявить его в вашей форме и присвоить ему соответствующий класс в форме_загрузки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...