Laden...

best practise: Event einer aggregierten Klasse weiterleiten

Erstellt von tabstop vor 12 Jahren Letzter Beitrag vor 12 Jahren 9.073 Views
T
tabstop Themenstarter:in
94 Beiträge seit 2007
vor 12 Jahren
best practise: Event einer aggregierten Klasse weiterleiten

Ich frage mich, was der beste Weg ist, ein Event einer aggregierten Klasse weiterzuleiten. Dazu folgender Code (KlasseA soll von aussen benutzt werden):


public class KlasseB
{
  public event EventHandler EventVonB;

  public void DoSomething()
  {
    OnEventVonB();
  }

  protected virtual void OnEventVonB()
  {
    EventHandler tmp = EventVonB;
    if (tmp != null)
    {
      tmp(this, new EventArgs());
    }
  }
}


public class KlasseA
{
  private KlasseB klasseB;

  public event EventHandler EventVonA
  {
    add { this.klasseB.EventVonB += value; }
    remove { this.klasseB.EventVonB -= value; }
  }

  public KlasseA()
  {
    this.klasseB = new KlasseB();
  }

  public void DoSomethingWithB()
  {
    this.klasseB.DoSomething();
  }
}

Wie macht ihr das? Insbesondere, falls noch eine KlasseC hinzukäme, die in KlasseB benutzt wird und man möchte das Event von KlasseC verfügbar machen.

Alternativ hätte ja auch KlasseA das Event von KlasseB abonnieren können und dieses durchreichen können. Nur würde ich am liebsten die ganze Aufrufkette so klein wie möglich halten.

A
764 Beiträge seit 2007
vor 12 Jahren

Wie praktisch. Du ersparst mir, diese Frage zu stellen.

Also ich habs bisher durchgereicht bis zur Klasse C. Glaube aber nicht so recht, dass das best practise ist.

2.298 Beiträge seit 2010
vor 12 Jahren

Also mir ist nur die Möglichkeit bekannt, das Event von innen nach außen zu reichen.

Ich habe bisher noch keine Andere Lösung gesehen. Falls dennoch jemand eine bessere Lösung kennt wäre ich auch interessiert an dieser.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

A
764 Beiträge seit 2007
vor 12 Jahren

und wie machst du das bei 3 klassen?

klasseC -> klasseB -> klasseA

oder irgendwie klasseC --> klasseA

2.298 Beiträge seit 2010
vor 12 Jahren

Ich reiche es der Hierarchie nach durch.

also eben KlasseC -> Klasse B - > Klasse A

Klasse C -> Klasse A würde bedeuten, dass Klasse A Klasse C kennt, oder Klasse C öffentlich über Klasse B zugänglich ist. Und beides wäre ja wiederum nicht wirklich sauber.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

G
538 Beiträge seit 2008
vor 12 Jahren

Durch das durchreichen hebelst du aber das private aus.
Du kannst nun nämlich beim Event den sender speichern und zugreifen, obwohl er private war.

Das kannst du verhindern, indem du das Event aus B in A abbonnierst und damit dann ein eigenen Event in A feuerst.
Das wiederum hat den Vorteil, dass du das Event aus B austauschen kannst, ohne was an Klassen, die A nutzen ändern zu müssen.

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

2.298 Beiträge seit 2010
vor 12 Jahren

Falls du dich damit auf meine Aussage stützt. Ich meinte eher folgendes:


class KlasseA
{
     private KlasseB _klasseB = new _klasseB();

     public event EventHandler SomeEvent;

     public KlasseA()
     {
         this._klasseB.SomeEvent += new EventHandler(SomeHandler);
     }

     private void SomeHandler(Object sender, EventArgs e)
     {
             if(SomeEvent != null)
                  SomeEvent(this, e);
     }
}

class KlasseB
{
     private KlasseC _klasseC = new _klasseC();

     public event EventHandler SomeEvent;

     public KlasseB()
     {
         this._klasseC.SomeEvent += new EventHandler(SomeHandler);
     }

     private void SomeHandler(Object sender, EventArgs e)
     {
             if(SomeEvent != null)
                  SomeEvent(this, e);
     }
}

class KlasseC
{
     public event EventHandler SomeEvent;

     public SomeMethod()
     {
           // some code

          if(SomeEvent != null)
               SomeEvent(this, EventArgs.Empty);
     }

}


Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

6.911 Beiträge seit 2009
vor 12 Jahren

Hallo,

dieses "Bubbling" ist schon die best practice.
Passend dazu: Event weitergeben über mehrere Applikationsschichten

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

U
1.688 Beiträge seit 2007
vor 12 Jahren

Hallo,

s. auch Ausführung ohne Dispatcher-Instanz an den GUI-Thread delegieren ff bzgl. "Konvention" - entscheidend ist eben, dass der "oberste" Aufrufer mit dem "sender" aus den unteren Klassen i. allg. nichts anfangen kann/darf und diesen auch gar nicht kennen sollte (Implementierungsdetails können sich ändern).

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo zusammen,

in dem verlinkten Thread (Ausführung ohne Dispatcher-Instanz an den GUI-Thread delegieren) ist es etwas verstreut und es geht dort auch noch um anderen Themen. Daher hier die relevantem Infos zusammengefasst:

Der EventHandler muss für genau das Objekt registriert sein, für das der Event ausgelöst wird.

Um einen Event ins GUI [bzw. allgemeiner gesprochen zum letztlichen Empfänger] zu bekommen, kann es nötigt sein, dass zwischengeschaltete Objekte den ursprünglichen Event fangen und dann selbst einen eigenen Event auslösen.

Wie umständlich das [bei mehreren Stufen] ist, hängt davon ab, von wievielen unterschiedlichen Klassen die Objekte sind. Wenn es nur eine Klasse ist, braucht man vom Code her nur einen Event zu schreiben, auch wenn der zur Laufzeit zehnmal von Objekt zu Objekt gefeuert wird.

Zwar könnte man über diese Syntax [
>
] im Prinzip einen EventHandler, der für das übergeordnete Objekt registriert wird, bei einem untergeordneten Objekt registrieren, so dass ein im untergeordneten Objekt gefeuerter Event ohne Umwege beim EventHandler ankommt, aber stimmt dann leider der sender-Parameter nicht mit dem überein, was der EventHandler erwarten darf. Der erwartet ja als Sender das Objekt, bei dem er den Event registriert hat, es kommt aber ein Objekt, welches er überhaupt nicht kennt [und welches normalerweise gar nicht bekannt sein soll]. Daher verbietet sich diese Vorgehensweise.

Ob das [dass der Sender immer das Objekt sein muss, bei man den Event registriert hat] jetzt irgendwo explizit als Regel steht, weiß ich nicht, aber eine Konvention ist es auf jeden Fall. Als sender kommt nur das Objekt in Betracht, bei dem man den Event abonniert hat. Das kann man z.B. in Windows Forms sehen: Wenn du im Form KeyDown abonnierst und KeyPreview auf true setzt und dann in einer TextBox auf dem Form Text eingibst, dann ist der Sender das Form und nicht die TextBox, denn man hat ja das Event des Forms und nicht das der TextBox abonniert.

Ob es praktisch wäre, die tatsächliche Quelle zu erfahren, steht auf einem anderen Blatt und hängt auch von den genauen Umständen ab. Wenn der sender z.B. eine interne oder private Klasse ist, wäre die Bekanntgabe mindestens ungünstig, wenn nicht sogar schädlich. In dem KeyPreview-Beispiel könnte es dagegen schon praktisch sein, die tatsächliche Quelle zu kennen. Aber das müsste man dann wirklich über die EventArgs machen.

herbivore

Suchhilfe: 1000 Worte, Event, Events, Ereignis, Ereignisse, weiterleiten, Weiterleitung, weitergeleitet, weitergeleitete, durchreichen, durchgereicht, durchgereichte, route, routen, routing, verschachtelt, verschachtelte, verschachteln, Verschachtelung, geschachtelt, geschachtelte, kaskadiert, kaskadierte, kaskadieren, Kaskade, verkettet, verkettete, verketten, Kette, durchschleifen, durchgeschleift