2010-01-29 15 views
7

Próbuję poznać niektóre zasady WCF, wykonując przykład aplikacji WCF (z Sacha Barber).GetInvocationList zdarzenia w VB.NET

Teraz chciałbym przekonwertować następujące funkcje w 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); 
     } 
    } 
} 

ale mam pewne problemy, ponieważ następujący kod nie jest akceptowana przez kompilator

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 

mówi

Publiczne współdzielone wydarzenie ChatEvent (nadawca Jako obiekt, e jako ChatEventArgs) "jest wydarzenie, a nie może być wywołana bezpośrednio

Jadąc do punktu, jest wtedy możliwe w VB.NET uzyskać teleskopowe połączone z pewnego zdarzenia w jakiś inny sposób?

Odpowiedz

7

użycie ChatEventEvent (lub EventName Event)

Nie pokaże się w intellisense, ale członkowie to będzie.

VB.NET tworzy zmienną za kulisy, aby ukryć złożoność z kodera ...

ta jest dostępna tylko w klasie, który deklaruje zdarzenie (albo jego potomkowie)

+0

Pamiętaj, że używasz nieudokumentowanego członka na swojej klasie i (o ile się nie mylę), zasady dotyczące nazewnictwa nie mają takiego samego znaczenia w przyszłych wersjach kompilatora. –

+0

@Adam - Tak, zdecydowanie nieudokumentowane, o ile widziałem, ale nie widzę, żeby je zmieniały, chyba że mają ku temu jakiś powód lub przynajmniej oferują alternatywę. W każdym razie jest to jedyny sposób, w jaki możesz to zrobić obecnie, bez zajmowania się wszystkimi wydarzeniami na własną rękę, jak w twoim przykładzie. Twój nadal będzie działał, jeśli go zmienią, ale wolałbym zapisać tę pracę, zważywszy na prawdopodobieństwo jej zmiany. –

5

Najprawdopodobniej próbujesz napisać ten kod w klasie będącej potomkiem klasy, która deklaruje zdarzenie ChatEvent. Nie można tego zrobić, ponieważ zdarzenia mogą być traktowane jako zmienne (w tym wywoływanie ich) w klasie, która je deklaruje. Wynika to z tego, że słowo kluczowe event faktycznie wskazuje kompilatorowi, że musi wykonać pewne transformacje zza kulis.

Co się zdarzyło

Rozważmy następującą deklarację:

Public Event MyEvent as EventHandler 

dość proste, prawda? Co to właściwie nie jest jednak to (po prostu nie go zobaczyć)

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 

A kiedy wywołania zdarzenia:

RaiseEvent MyEvent(Me, EventArgs.Emtpy) 

To faktycznie wywołuje kod w bloku RaiseEvent.

Edit

Jeśli wydarzenia w VB.NET nie mogą być traktowane jako zmienne nigdzie (mogą one być traktowane jako zmienne w uznającej klasy w języku C#, który jest dlaczego C# przykład kompiluje) wtedy musisz samodzielnie zaimplementować to wydarzenie. Zobacz MSDN page on the Event statement, aby uzyskać więcej informacji o tym, jak to zrobić. Aby krótko opowiedzieć, będziesz chciał w jakiś sposób przechowywać wiele programów obsługi zdarzeń (lub użyć pojedynczej procedury obsługi zdarzenia wraz z GetInvocationList, jak próbujesz zrobić teraz). W blokach kodu AddHandler i RemoveHandler będziesz dodawać i usuwać z listy programów obsługi zdarzeń (odpowiednio).

Można użyć coś takiego:

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 

Więc teraz, jeśli zadzwonisz

RaiseEvent MyEvent(Me, EventArgs.Emtpy) 

Podniesie to wydarzenie w modzie nie zwariować.

+0

Dziękuję dla odpowiedzi, ale nie sądzę, że to moja sprawa. Moja klasa nazywa się ChatService i deklaruje zarówno Shared Event ChatEvent, jak i Sub BroadcastMessage, gdzie próbuję uzyskać listę InvocationList w ChatEvent. – Drake

+0

@marco: Sprawdź, czy moje zmiany są bardziej pomocne –

+1

w powyższym pierwszym przykładzie, compilerGeneratedName to * zawsze * nazwa zdarzenia, po której następuje słowo "Event", a więc ChatEventEvent, w tym przypadku. –