我正在开发一个用于其他开发人员的类库,并允许他们使用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
答案 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。由于它将成为一个共享库,我不认为你需要执行消费者的事件处理程序。你的图书馆的工作就是发动事件,让消费者知道发生了什么。由他们来处理或不处理事件。
我会说你的财产是多余的。它们本质上是事件处理程序。