Dot-Net

VB.NET 中事件的 GetInvocationList

  • January 29, 2010

我正在嘗試通過遵循 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);
       }
   }
}

但是我有一些問題,因為編譯器不接受以下程式碼

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

它說

Public Shared Event ChatEvent(sender As Object, e As ChatEventArgs)‘是一個事件,不能直接呼叫

說到重點,在 VB.NET 中是否有可能以其他方式將處理程序連結到某個事件?

使用 ChatEventEvent(或EventName事件)

它不會出現在智能感知中,但它的成員會。

VB.NET 在幕後創建一個變數,以隱藏編碼器的複雜性……

這僅在聲明事件(或其後代)的類中可用

您可能試圖在聲明ChatEvent事件的類的後代類中編寫此程式碼。這是無法做到的,因為事件只能在聲明它們的類中被視為變數(包括呼叫它們)。這是因為event關鍵字實際上向編譯器表明它需要執行一些幕後轉換。

發生什麼了

考慮這個聲明:

Public Event MyEvent as EventHandler

很簡單,對吧?然而,這實際上做了什麼(你只是看不到它)

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

當您呼叫事件時:

RaiseEvent MyEvent(Me, EventArgs.Emtpy)

它實際上呼叫了RaiseEvent塊中的程式碼。

編輯

如果 VB.NET 中的事件在任何地方都不能被視為變數(它們可以被視為 C# 中聲明類中的變數,這就是 C# 範例編譯的原因),那麼您必須自己顯式地實現該事件。有關如何執行此操作的更多資訊,請參閱Event 語句上的 MSDN 頁面。長話短說,您將需要某種方式來儲存多個事件處理程序(或使用單個事件處理程序以及GetInvocationList,就像您現在嘗試做的那樣)。在您的AddHandlerRemoveHandler程式碼塊中,您將(分別)添加到事件處理程序列表和從事件處理程序列表中刪除。

你可以使用這樣的東西:

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

所以現在,如果你打電話

RaiseEvent MyEvent(Me, EventArgs.Emtpy)

它將以您期望的方式引發事件。

引用自:https://stackoverflow.com/questions/2162294