VB.NET中事件的GetInvocationList

Dra*_*ake 8 .net vb.net events delegates

我正在尝试通过遵循WCF应用程序(来自Sacha Barber)的示例来学习一些WCF原则.

现在我想将以下函数转换为VB.NET

private void BroadcastMessage(ChatEventArgs e)
{

    ChatEventHandler temp = ChatEvent;

    if (temp != null)
    {
        foreach (ChatEventHandler handler in temp.GetInvocationList())
        {
            handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我遇到了一些问题,因为编译器不接受以下代码

Private Sub BroadcastMessage(ByVal e As ChatEventArgs)

    Dim handlers As EventHandler(Of ChatEventArgs) = ChatEvent

    If handlers IsNot Nothing Then

        For Each handler As EventHandler(Of ChatEventArgs) In handlers.GetInvocationList()

            handler.BeginInvoke(Me, e, New AsyncCallback(AddressOf EndAsync), Nothing)

        Next

    End If

End Sub
Run Code Online (Sandbox Code Playgroud)

它说

公共共享事件ChatEvent(sender As Object,e As ChatEventArgs)'是一个事件,不能直接调用

接下来,是否有可能在VB.NET中获得以某种其他方式链接到某个事件的处理程序?

Ric*_*tad 8

使用ChatEventEvent(或EventName事件)

它不会出现在intellisense中,但它的成员会.

VB.NET在幕后创建一个变量,以隐藏编码器的复杂性......

这仅在声明事件的类(或可能是其后代)中可用


Ada*_*son 6

您可能尝试将此代码编写在类中,该类是声明该ChatEvent事件的类的后代.这是不可能的,因为事件只能在声明它们的类中被视为变量(包括调用它们).这是因为event关键字实际上向编译器指示它需要执行一些幕后转换.

怎么了

考虑这个声明:

Public Event MyEvent as EventHandler
Run Code Online (Sandbox Code Playgroud)

很简单吧?然而,实际上这是做什么的(你只是看不到它)

Private compilerGeneratedName as EventHandler

Public Event MyEvent as EventHandler
    AddHandler(ByVal value as EventHandler)
        compilerGeneratedName += value
    End AddHandler
    RemoveHandler(ByVal value as EventHandler)
        compilerGeneratedName -= value
    End RemoveHandler
    RaiseEvent(ByVal sender as Object, ByVal e as EventArgs)
        compilerGeneratedName.Invoke(sender, e)
    End RaiseEvent
End Event
Run Code Online (Sandbox Code Playgroud)

当你调用这个事件时:

RaiseEvent MyEvent(Me, EventArgs.Emtpy)
Run Code Online (Sandbox Code Playgroud)

它实际上调用了RaiseEvent块中的代码.

编辑

如果VB.NET中的事件不能在任何地方被视为变量(它们可以被视为C#中声明类中的变量,这就是您的C#示例编译的原因),那么您必须自己明确地实现该事件.有关如何执行此操作的详细信息,请参阅Event语句中的MSDN页面.总而言之,您需要一些方法来存储多个事件处理程序(或者使用单个事件处理程序GetInvocationList,正如您现在尝试的那样).在您AddHandler和RemoveHandler代码块中,您将分别添加和删除事件处理程序列表.

你可以使用这样的东西:

Private myEventList as New List(Of EventHandler)

Public Custom Event MyEvent as EventHandler
    AddHandler(ByVal value as EventHandler)
        myEventList.Add(value)
    End AddHandler
    RemoveHandler(ByVal value as EventHandler)
        myEventList.Remove(value)
    End RemoveHandler
    RaiseEvent(ByVal sender as Object, ByVal e as EventArgs)
        For Each evt in myEventList
           evt.BeginInvoke(sender, e, New AsyncCallback(AddressOf EndAsync), Nothing)
        Next
    EndRaiseEvent
End Event
Run Code Online (Sandbox Code Playgroud)

所以现在,如果你打电话

RaiseEvent MyEvent(Me, EventArgs.Emtpy)
Run Code Online (Sandbox Code Playgroud)

它将以您期待的方式提升活动.