代码之家  ›  专栏  ›  技术社区  ›  hmcclungiii

使用委托和声明事件

  •  3
  • hmcclungiii  · 技术社区  · 15 年前

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

    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等操作吗?

    谢谢你的建议…我认为我是多余的,不需要无意义的代码,更不用说避免干涸的原则了。

    编辑只想发布代码的其余部分,并强调此类实例执行的“工作”是在单独的线程上完成的。/编辑

    #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 回复  |  直到 15 年前
        1
  •  4
  •   Mark Cidade    15 年前

    我想说的是完全取消你的代表。

    你的代表正在做与活动完全相同的事情。您几乎是在编写自己的事件管道,而不是使用框架的事件调用。一个事件和你写的差不多,只是它更容易使用,而且更容易取消订阅。

    提供两者都没有好处——活动做了你的“代表”所做的一切,而且更清楚。

    (先前:)

    如果你把它开发成一个类库,我建议你让你的类不被密封,并遵循更标准的方法。允许逻辑被重写或插入代码并允许事件发生的正常方法是为子类化提供钩子。

    委托可以在这种情况下使用,以允许用户插入自己的逻辑。然而,在许多情况下,具有受保护的虚拟功能使这一点更加清晰,并且更容易实现。

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

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

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

    在极少数情况下,我提供委托的地方是类或方法需要由用户添加逻辑。在这种情况下,您可以提供一个抽象基类,或者为该逻辑传递一个委托。Linq中的.where()方法就是一个很好的例子。如果没有用于筛选的谓词,WHERE是无用的,因此在这种情况下,传入委托是有意义的。不过,请注意,没有与此相关联的事件-它实际上是用来提供不同的功能的。

        2
  •  0
  •   irperez    15 年前

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

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

    当然,一定要在你图书馆的任何地方举办这个活动。任何客户端开发人员都将是向事件添加处理程序的开发人员。

    它不是多余的,只是没有必要,除非您的库要处理该类中的任何事件。

        3
  •  0
  •   Community Mike Kinghan    7 年前

    您可以使用 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 . 因为它将是一个共享的图书馆,我不认为 需要执行使用者的事件处理程序。您的图书馆的工作就是启动活动,让消费者知道发生了什么。由他们决定是否处理事件。

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