2009-06-30 19 views
35

Używam klasy, która przekazuje zdarzenia w języku C#. Zastanawiam się, czy istnieje sposób robienia tego, który wymaga mniejszego narzutu kodu.Przekazywanie zdarzeń w języku C#

Oto przykład tego, co do tej pory miałem.

class A 
{ 
    public event EventType EventA; 
} 

class B 
{ 
    A m_A = new A(); 
    public event EventType EventB; 

    public B() 
    { 
     m_A.EventA += OnEventA; 
    } 

    public void OnEventA() 
    { 
     if(EventB) 
     { 
     EventB(); 
     } 
    } 
} 

Klasa A podnosi oryginalne wydarzenie. Klasa B przekazuje ją jako EventB (co jest w zasadzie tym samym zdarzeniem). Klasa A jest ukryta przed innymi modułami, więc nie może bezpośrednio zasubskrybować EventA.

Co staram się zrobić, to zmniejszyć obciążenie kodu w klasie B w celu przekazania zdarzenia, ponieważ zazwyczaj nie ma rzeczywistej obsługi zdarzeń w klasie B. Będę też mieć kilka różnych zdarzeń, więc będzie to wymagało pisania wiele metod OnEvent() w klasie B, które służą tylko do przekazywania zdarzeń.

Czy to możliwe, aby automatycznie połączyć Eventa do EventB w jakiś sposób, tak, że mam coś takiego:

class B 
{ 
    A m_A = new A(); 
    public event EventType EventB; 

    public B() 
    { 
     m_A.EventA += EventB; // EventA automatically raises EventB. 
    } 
} 

Używam kompilatora C# 2.0 btw.

+0

wielkie pytanie, zwłaszcza, że ​​nie należy zapominać, aby wypisać się z Eventa , w przeciwnym razie może wystąpić wyciek pamięci (twój obiekt B pozostanie w pamięci tak długo, jak A, nawet jeśli nie będzie już potrzebny). – dbkk

Odpowiedz

64

Absolutnie:

class B 
{ 
    private A m_a = new A(); 

    public event EventType EventB 
    { 
     add { m_a.EventA += value; } 
     remove { m_a.EventA -= value; } 
    } 
} 

Innymi słowy, subskrypcja EventB/code wypisania właśnie przechodzi subskrypcji/wypisania wniosków na celu Eventa.

Pamiętaj, że to nie zezwala na podniesienie zdarzenia tylko dla subskrybentów, którzy zasubskrybowali EventB. Przypomina to przekazywanie czyjegoś adresu bezpośrednio firmie zajmującej się marketingiem masowym, podczas gdy twój oryginalny sposób przypomina raczej subskrybowanie firmy masowego marketingu i pozwala ludziom prosić o przesłanie im kopii wiadomości.

+11

To znaczy, że subskrybent 'B.EventB' dostaje niewłaściwego nadawcę (' A' zamiast 'B'), co może być ważne ... –

+3

Prawda, prawda ... w zależności od tego, co postrzegasz jako "źle" oczywiście. Prawdopodobnie warto to przynajmniej udokumentować. –

9

IMO, Twój oryginalny kod jest (mniej więcej) poprawny. W szczególności umożliwia podanie poprawnej instancji sender (która powinna być instancją B dla osób, które myślą, że subskrybują wydarzenie pod numerem B).

Istnieją pewne sztuczki mające na celu ograniczenie kosztów stałych w czasie wykonywania, jeśli zdarzenie nie jest zapisany, ale to dodaje więcej kod:

class B { 
    A m_A = new A(); 
    private EventType eventB; 
    public event EventType EventB { 
     add { // only subscribe when we have a subscriber ourselves 
      bool first = eventB == null; 
      eventB += value; 
      if(first && eventB != null) m_A.EventA += OnEventB; 
     } 
     remove { // unsubscribe if we have no more subscribers 
      eventB -= value; 
      if(eventB == null) m_A.EventA -= OnEventB; 
     } 
    } 

    protected void OnEventB(object sender, EventArgsType args) { 
     EventType handler = eventB; 
     if(handler !=null) { 
     handler(this, args); // note "this", not "sender" 
     } 
    } 
} 
Powiązane problemy