【问题标题】:Different ways of raising a Custom Event in .NET Framework在 .NET Framework 中引发自定义事件的不同方法
【发布时间】:2016-06-10 12:26:29
【问题描述】:

我知道在 VB .Net 中可以定义您的自定义事件处理程序。

这是一个类知道另一个类何时监听其事件的一种方式。本示例代码来自MSDN

Private Events As EventHandlerList

Public Custom Event MyEvent As EventHandler
    AddHandler(value As EventHandler)
        Events.AddHandler("Test", value)
    End AddHandler

    RemoveHandler(value As EventHandler)
        Events.RemoveHandler("Test", value)
    End RemoveHandler

    RaiseEvent(sender As Object, e As EventArgs)
        CType(Events("Test"), EventHandler).Invoke(sender, e)
    End RaiseEvent
End Event

现在,您可以通过以下方式引发自定义事件:

Private Sub MySub()
    RaiseEvent MyEvent(Me, EventArgs.Empty)
End Sub

到目前为止一切顺利,完全没有问题。

我的问题是,由于在我的班级中我可以直接访问 EventHandlerList,我可以在自定义事件处理程序之外调用它吗? 如果我这样做了,这个 sub 和上面那个有什么区别吗?

Private Sub MySub2()
    CType(Events("Test"), EventHandler).Invoke(Me, EventArgs.Empty)
End Sub

我知道这可能根本不是什么好习惯,我只是好奇,因为我可能有一个函数将事件名称传递为String,因此引发事件的方式可能对我有用,我会的类似:

Private Sub RaiseCustomEvent(EventName As String, Ev as EventArgs)
    CType(Events(EventName), EventHandler).Invoke(Me, Ev)
End Sub

【问题讨论】:

  • 该 MSDN 示例依赖于键值 (a String) 为 Interned。关键参数是Object 类型,EventHandlerList.Item 属性在查找请求的处理程序时使用引用相等,而不是底层类型的默认比较器。最好显式声明一个密钥,即Private MyEventKey As New Object。此外,在尝试调用Invoke 之前,您应该验证Events(EventName) 的结果不是什么。
  • 如果您将自定义事件添加到 Form 类并且 1) 声明一个新的 EventHandlerList 用于存储事件以及 2) 随后通过创建方法的 VS IDE 附加事件处理程序,请注意使用Handles 子句。由于 VB 编译器的工作方式,生成的代码将尝试在 EventHandlerList 实例化之前将事件处理程序添加到 EventHandlerList。这会导致创建表单时出现空引用异常。

标签: .net vb.net custom-events


【解决方案1】:

我的问题是,由于在我的班级中我可以直接访问 EventHandlerList,我可以在自定义事件处理程序之外调用它吗?

是的。

如果我这样做了,这个 sub 与上面那个有什么区别吗?

没有。 RaiseEvent 语句只是调用事件声明的 RaiseEvent 部分。 VB.NET 规范说:

RaiseEvent 声明采用与事件委托相同的参数,并将在执行 RaiseEvent 语句时调用。

但请注意,MSDN 示例已损坏 --- 如果没有附加事件处理程序 (Fiddle),它将引发 NullReferenceException

Public Module Module1
    Public Sub Main()
        Dim x As New T()
        x.RaiseTestEvent()
    End Sub
End Module

Public Class T
    Private Events As New System.ComponentModel.EventHandlerList()

    Public Custom Event MyEvent As EventHandler
        AddHandler(value As EventHandler)
            Events.AddHandler("Test", value)
        End AddHandler

        RemoveHandler(value As EventHandler)
            Events.RemoveHandler("Test", value)
        End RemoveHandler

        RaiseEvent(sender As Object, e As EventArgs)
            CType(Events("Test"), EventHandler).Invoke(sender, e)
        End RaiseEvent
    End Event

    Public Sub RaiseTestEvent()
        ' Throws NullReferenceException if no event handler is attached.
        RaiseEvent MyEvent(Me, EventArgs.Empty)
    End Sub
End Class

对于“常规”事件,如果没有附加处理程序 (Fiddle),RaiseEvent 只是一个 NO-OP。 VB 规范说:

使用提供的参数(如果有),将 RaiseEvent 语句作为对事件委托的 Invoke 方法的调用进行处理。如果委托的值为 Nothing,则不会引发异常。

【讨论】:

  • 感谢您提供的准确信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多