如何向事件添加操作

时间:2017-10-23 11:43:25

标签: vb.net handler

我在通用类中有一个事件

Public class SomeClass
    Public Event ChangeEvent(oldValue As T, newValue As T)

    ' some code..
End Class

我有一个复杂的方法,我传递Action(Of T),它应该被添加到事件中,然后再次删除。它看起来像下面这样:

Public Sub SomeSub(listener As Action(Of T, T)
    AddHandler ChangeEvent, listener
    ' some code
    RemoveHandler ChangeEvent, listener
End Sub

但是在这两行上编译器都给出了以下错误:

  

'Action(Of T,T)'类型的值无法转换为'ChangeEventHandler'。

以下有效,但我无法删除处理程序,因为它是lambda表达式。

Public Sub SomeSub(listener As Action(Of T, T)
    AddHandler ChangeEvent, Sub(x, y) listener(x, y)
End Sub

是否有一个解决方案不涉及我将lambda存储为成员?请注意,我无法更改活动。我只控制添加侦听器的方法。

2 个答案:

答案 0 :(得分:1)

最好是显式声明事件处理程序委托,而不是让Visual Basic隐式地执行它:

Public Class SomeClass(Of T)
    Public Delegate Sub ChangeEventHandler(oldValue As T, newValue As T)
    Public Event ChangeEvent As ChangeEventHandler

    ' some code..
End Class

通过这种方式,您可以将委托指定为方法的参数,从而为编译器提供正确的签名,并且您可以添加和删除它:

Public Sub SomeSub(listener As ChangeEventHandler)
    AddHandler ChangeEvent, listener
    ' some code...
    RemoveHandler ChangeEvent, listener
End Sub

现在你和编译器都很开心! :)

答案 1 :(得分:0)

它实际上是这样的:

expect(mockService.coolMethod).ToHaveBeenCalled();
// or
mockService.coolMethod.and.returnValue('I am so cool');

这将添加处理程序,并在事件执行后立即将其删除。因此,lambda中的代码将只执行一次。

诀窍是要单独声明一个处理程序,因为在lambda中,您需要引用该变量以删除该处理程序。

您根本不需要保留任何成员变量,运行时将为您存储封装的变量。


但是,您必须确保该事件确实被触发(至少一次)。如果不是这样,则可能会导致内存泄漏,因为事件处理程序永远不会删除。