2009-06-30 5 views
35

Ich verwende eine Klasse, die Ereignisse in C# weiterleitet. Ich habe mich gefragt, ob es eine Möglichkeit gibt, es zu tun, die weniger Code-Overhead benötigt.Weiterleiten von Ereignissen in C#

Hier ist ein Beispiel von dem, was ich bisher habe.

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(); 
     } 
    } 
} 

Klasse A löst das ursprüngliche Ereignis aus. Class B leitet es als EventB (das ist im Wesentlichen das gleiche Ereignis). Klasse A ist vor anderen Modulen verborgen, sodass sie EventA nicht direkt abonnieren können.

Was ich versuche zu reduzieren ist die Code-Overhead in Klasse B für die Weiterleitung des Ereignisses, da es in der Regel keine echte Behandlung der Ereignisse in Klasse B gibt. Auch ich werde mehrere verschiedene Ereignisse haben, so dass es schreiben würde viele OnEvent() - Methoden in Klasse B, die nur dazu dienen, die Ereignisse weiterzuleiten.

Ist es möglich, automatisch Eventa zu EventB in irgendeiner Weise zu verbinden, also würde ich so etwas wie dieses:

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

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

Ich bin mit einem C# 2.0-Compiler btw.

+0

Große Frage, vor allem, da Sie nicht von Eventa austragen sollten vergessen Andernfalls könnte ein Speicherverlust auftreten (Ihr Objekt B bleibt so lange im Speicher, wie A ist, auch wenn es nicht mehr benötigt wird). – dbkk

Antwort

64

Absolut:

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

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

Mit anderen Worten, der EventB Abonnement/Abbestellung Code übergibt nur die Zeichnungs-/Abmeldeanfragen auf Eventa.

Beachten Sie, dass dies das Ereignis nur für Abonnenten, die EventB abonniert haben, jedoch nicht auslösen kann. Es ist so, als würde man jemandes Adresse direkt an eine Massenmarketing-Firma weiterleiten, während der ursprüngliche Weg eher darin besteht, die Massenmarketing-Firma selbst zu abonnieren und es den Leuten erlaubt, Sie zu bitten, Kopien der Mails an sie zu senden.

+11

Es bedeutet, dass ein Abonnent von 'B.EventB' den falschen Absender bekommt (' A' anstelle von 'B'), obwohl - das kann wichtig sein ... –

+3

Wahr, wahr ... je nachdem, was Sie als anzeigen "falsch" natürlich. Mindestens eine Dokumentation wert. –

9

IMO, Ihr ursprünglicher Code ist (mehr oder weniger) korrekt. Insbesondere ermöglicht es Ihnen, die richtige sender (die die B-Instanz für Personen sein sollte, die denken, dass sie ein Ereignis unter B abonnieren) bereitstellen.

Es gibt einige Tricks, um die Gemeinkosten zur Laufzeit zu reduzieren, wenn das Ereignis nicht abonniert haben, aber dies fügt mehr Code:

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" 
     } 
    } 
}