使用委托和声明事件

时间:2009-03-20 17:00:43

标签: .net delegates event-handling

我正在开发一个用于其他开发人员的类库,并允许他们使用WithEvents(或类似的其他语言)声明我的类的实例,并允许他们使用类中定义的Delegates 。我这样做是不是多余了?

Public Delegate Sub TimerElapsedDelegate(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event TimerElapsed(ByVal sender As Object, ByVal e As System.EventArgs)
Private _TimerElapsed As TimerElapsedDelegate = Nothing

或者我应该只声明事件并让他们执行AddHandler等,?

感谢您对此提出任何建议......我认为我是多余的,不需要无意义的代码,更不用说避免干燥原则了。

{edit}只是想发布剩余的代码,并强调这个类的实例“工作”是在一个单独的线程上完成的。{/ edit}

#Region "Delegates"
Public Delegate Sub TimerElapsedDelegate(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event TimerElapsed(ByVal sender As Object, ByVal e As System.EventArgs)
Private _TimerElapsed As TimerElapsedDelegate = Nothing
Public Property OnTimerElapsed() As TimerElapsedDelegate
    Get
        Return _TimerElapsed
    End Get
    Set(ByVal value As TimerElapsedDelegate)
        If value Is Nothing Then
            _TimerElapsed = Nothing
        Else
            If _TimerElapsed Is Nothing Then
                _TimerElapsed = value
            Else
                _TimerElapsed = System.Delegate.Combine(_TimerElapsed, value)
            End If
        End If
    End Set
End Property
Private Sub TriggerTimerElapsed()
    If OnTimerElapsed IsNot Nothing Then
        OnTimerElapsed.Invoke(Me, New System.EventArgs)
    End If
    RaiseEvent TimerElapsed(Me, New System.EventArgs)
End Sub

Public Delegate Sub ItemReadyForQueueDelegate(ByVal sender As Object, ByVal e As System.EventArgs)
Public Event ItemReadyForQueue(ByVal sender As Object, ByVal e As System.EventArgs)
Private _ItemReadyForQueue As ItemReadyForQueueDelegate = Nothing
Public Property OnItemReadyForQueue() As ItemReadyForQueueDelegate
    Get
        Return _ItemReadyForQueue
    End Get
    Set(ByVal value As ItemReadyForQueueDelegate)
        If value Is Nothing Then
            _ItemReadyForQueue = Nothing
        Else
            If _ItemReadyForQueue Is Nothing Then
                _ItemReadyForQueue = value
            Else
                _ItemReadyForQueue = System.Delegate.Combine(_ItemReadyForQueue, value)
            End If
        End If
    End Set
End Property
Private Sub TriggerItemReadyForQueue(ByVal oItem As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate)
    If OnItemReadyForQueue IsNot Nothing Then
        OnItemReadyForQueue.Invoke(Me, New ItemReadyForQueueEventArgs(oItem))
    End If
    RaiseEvent ItemReadyForQueue(Me, New ItemReadyForQueueEventArgs(oItem))
End Sub
Public Class ItemReadyForQueueEventArgs
    Inherits System.EventArgs
    Private _ReportTemplate As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate = Nothing
    Public ReadOnly Property ReportTemplate() As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate
        Get
            Return _ReportTemplate
        End Get
    End Property
    Public Sub New(ByVal oReportTemplate As h3Budgeteer.FileSystem.ReportTemplateFile.ReportTemplate)
        _ReportTemplate = oReportTemplate
    End Sub
End Class

结束地区

3 个答案:

答案 0 :(得分:4)

我想说完全删除你的代表。

你的代表正在做与事件完全相同的事情。你几乎在编写自己的事件管道而不是使用框架的Event调用。事件几乎就是你所写的,除了它更容易使用,并且更容易取消订阅事件。

提供两者都没有任何好处 - 该事件可以完成“委托”所做的所有事情,而且更加清晰。

(以前:)

  

如果您将其作为一个类库进行开发,我建议您不要将您的课程密封,并遵循更标准的方法。允许逻辑被重写或插入代码并允许事件的常规方法是为子类化提供钩子。

     

代理可以在这种情况下使用,以允许用户插入自己的逻辑。但是,在许多情况下,拥有受保护的虚拟功能会使其更加清晰,并且更容易实现。

     

事件应该是一个事件,通知用户某些“事件”。这些应该是用户附加其委托的钩子。

     

例如,基本Windows窗体控件使用受保护的方法(即:OnMouseDown)和默认触发的事件(MouseDown),而不是提供委托和事件。

     

这允许用户对您的类进行子类化并覆盖逻辑(这可能是您需要委托的原因)以及处理事件。

     

在我提供代表的地方,在极少数情况下,您的类或方法需要用户添加逻辑。在这种情况下,您可以提供抽象基类,也可以拥有为该逻辑传入的委托。一个很好的例子是LINQ中的.Where()方法。如果没有用于过滤的谓词,那么无用,所以在这种情况下传递委托是有意义的。但请注意,没有与此相关的事件 - 它实际上提供了不同的功能。

答案 1 :(得分:0)

对于您的类库,您只需要编写公共事件代码行。

Public Event TimerElapsed(ByVal sender As Object, ByVal e As System.EventArgs)

确保在您的图书馆的任何地方举办活动。任何客户端开发人员都可以为事件添加处理程序。

它不是多余的,除非你的图书馆要处理该类的任何事件,否则它是没有必要的。

答案 2 :(得分:0)

您可以使用generic EventHandler删除委托。您所要做的就是创建自己的继承自EventArgs的类。

Public Class Foo
    Inherits EventArgs
End Class

Public Class Bar
    Public Event MyEvent As EventHandler(Of Foo)
End Class

我不认为你是多余的。请参阅this问题的第一个答案。添加一个空的事件处理程序将保证使用你的事件的人在不想听/处理事件时被触发时不会得到NullReferenceException。

- 编辑 -

看到您的代码后,我同意Reed。由于它将成为一个共享库,我不认为需要执行消费者的事件处理程序。你的图书馆的工作就是发动事件,让消费者知道发生了什么。由他们来处理或不处理事件。

我会说你的财产是多余的。它们本质上是事件处理程序。