VB.NET 通过引用调用事件处理程序

VB.NET calling event handlers by reference

来自 Deplhi,我习惯于使用简单的方法直接从实例调用事件处理程序

Button.OnMouseOver([arguments])

现在我在 VB.NET 上,但我找不到一种方法来触发事件的处理程序,而不实际触发事件。

对我在这里所做的一些解释:在创建新表单时,我解析其内容以根据变量设置所有颜色。 根据按钮是否启用,它有不同的颜色,但如果按钮在创建时被禁用,它仍然需要通过处理程序来更正其颜色。

这就是我正在使用的

AddHandler ButtonInstance.EnabledChanged, AddressOf Button_EnabledChanged
Button_EnabledChanged(ButtonInstance, New EventArgs)

这工作正常,但我仍然希望能够直接从它正在处理的对象调用该方法,只是因为我并不总是事先知道事件处理程序的名称。

我一直被指向 RaiseEvent,但它似乎没有满足我的需要。

有没有办法在不实际干扰实例的情况下检索事件的处理程序或触发它?

在不触发事件本身的情况下调用事件处理程序有什么意义?

如果您在代码中定义了事件,则可以使用 RaiseEvent EventName 触发它,但这不是 EnabledChanged 的情况,因为它是在基 class 中定义的。您还可以在其名称中添加事件后缀以使用它的处理程序等,例如 EventNameEvent.GetInvocationList

如果您的事件是在您无法修改的基 class 中声明的,您可以继承该 class 并调用应触发事件并调用所有处理程序的 OnEventName 方法。 OnEventName 方法的实际实现可以防止事件被触发。这取决于基础 class 实施。

手动查找和触发继承事件的事件处理程序需要反射。

简单的答案是否定的。我确信使用反射在技术上是可能的,以获取已添加到事件中的代表列表并调用每个代表,但这将是一个丑陋的 hack,只应在最绝望的情况下使用。如果你需要这样做,VB.NET 中最好的方法是设置一个事件处理程序,它总是在事件引发时被调用(这样你也可以自己直接调用它)然后包含一个列表然后依次调用的代表。换句话说,使用委托来创建您自己的类似事件的机制,从而提供您需要的灵活性。例如,像这样:

Private _clickActions As New List(Of Action)()

Public Sub AddClickAction(action As Action)
    _clickActions.Add(action)
End Sub

Public Sub PerformClickActions()
    For Each action As Action in _clickActions
        action?.Invoke()
    Next
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs)
    PerformClickActions()
End Sub

如果您需要在多个地方针对不同类型的事件执行此操作,那么为此类事件创建通用通用 class 似乎很容易。