События в базовых классах - PullRequest
3 голосов
/ 19 мая 2009

Хорошо, у меня есть базовый класс, который объявляет событие StatusTextChanged. Мой детский класс, конечно, не может напрямую вызвать это событие.

Итак, я получаю что-то вроде этого (для простоты):

Public MustInherit Class FooBase
    Public Event StatusTextChanged(ByVal StatusText As String)
    Protected Sub RaiseStatusTextChangedEvent(ByVal StatusText As String)
        RaiseEvent StatusTextChanged(StatusText)
    End Sub
End Class

А потом в детском классе звоню MyBase.RaiseStatusTextChangedEvent("something"). Есть ли лучший или более рекомендуемый способ сделать это?

edit: VB.NET или C #, в любом случае они работают практически одинаково.

edit: Итак, после ответов я нахожусь в базовом классе, затем просто устанавливаю свойство StatusText в дочернем классе ...

    Public Event StatusTextChanged(ByVal StatusText As String)
    Private _StatusText As String = "Idle."
    Public Property StatusText() As String
        Get
            Return _StatusText
        End Get
        Protected Set(ByVal value As String)
            RaiseEvent StatusTextChanged(value)
        End Set
    End Property

Ответы [ 5 ]

6 голосов
/ 19 мая 2009

Я бы сказал, что вы достаточно близки к рекомендованному пути (или, по крайней мере, к тому, который я бы порекомендовал).

Я бы сделал несколько изменений в вашем коде, если бы у меня был выбор:

  • Сделать StatusTextChanged Protected Overridable
  • Обтекание StatusText в пользовательском классе EventArgs
  • Измените объявление StatusTextChanged на Public Event StatusTextChanged As EventHandler(Of YourCustomEventArgs)

Полученный код:

Класс пользовательских событий:

Public Class TextEventArgs
    Inherits EventArgs

    Private _text As String

    Public Sub New(ByVal text As String)
        _text = text
    End Sub

    Public ReadOnly Property Text() As String
        Get
            Return _text
        End Get
    End Property

End Class

Реализация события в вашем базовом классе:

Public Event StatusTextChanged As EventHandler(Of TextEventArgs)
Protected Overridable Sub OnStatusTextChanged(ByVal e As TextEventArgs)
    RaiseEvent StatusTextChanged(Me, e)
End Sub

... и, наконец, строка кода для вызова события; либо в базовом классе, либо в классе, который его наследует:

OnStatusTextChanged(New TextEventArgs("some text"))

Это будет в большей степени соответствовать тому, как события создаются в остальной части .NET Framework.

1 голос
/ 19 мая 2009

Если для вашего дочернего класса нет особой необходимости переопределять метод базового класса, то я бы сказал, что вызов реализации базового класса является абсолютно лучшим решением.

0 голосов
/ 20 мая 2009

Вот мой код для события с делегатом и параметром текста статуса

Public Event Status As StatusEventHandler

Protected Overridable Sub OnStatus(ByVal e As StatusEventArgs)
    RaiseEvent Status(Me, e)
End Sub

Public Delegate Sub StatusEventHandler(ByVal sender As Object, _
   ByVal e As StatusEventArgs)

<System.Serializable()> _
Public Class StatusEventArgs
    Inherits System.EventArgs

    Public Sub New()
    End Sub

    Public Sub New(ByVal statusText As String)
        _StatusText = statusText
    End Sub

    ' Enter code here for event properties, etc.

    Private _StatusText As String = ""
    Public Property StatusText() As String
        Get
            Return _StatusText
        End Get
        Set(ByVal value As String)
            _StatusText = value
        End Set
    End Property


End Class
0 голосов
/ 19 мая 2009

Один из возможных вариантов - обернуть свойство Status в базовом классе, чтобы оно вызывало само событие при изменении. (в C # так как не знаю VB и не имею доступа к Visual Studio на данный момент)

private string _status;

public string Status
{
    get { return _status; }
    protected set
    {
        if (_status == value) return;
        _status = value;
        StatusChanged(value);
    }
}
0 голосов
/ 19 мая 2009

Это в значительной степени стандартный способ вызова событий в базовом классе через производный для этого типа сценария.

Однако это может немного измениться в зависимости от того, кто контролирует StatusText для иерархии. Если в FooBase есть конкретное вспомогательное поле StatusText, которое может быть изменено только через средства доступа, я бы не позволил дочернему элементу контролировать возникновение события StatusTextChanged. Вместо этого я бы принудительно вызвал события в Setter свойства StatusText. Это дает родительскому классу больше контроля над выполнением любых контрактов, которые ему нужны, когда и когда не вызывать указанное событие.

Однако если StatusText является свойством, которое должно быть определено производным классом, я бы выбрал отображаемый вами маршрут.

...