Idiomatische C # für Objekte, die nur interagieren, obwohl sie sich bei Ereignissen registriert haben

8

Ich bin unruhig darüber, wie ich ein einfaches Programm entworfen habe. Es gibt ein FileParser -Objekt mit OnFileOpened , OnLineParsed und OnFileClosed -Ereignissen, und mehrere Objekte, die kleinere Dateien basierend auf dem Inhalt der Datei erstellen, die FileParser analysiert.

Die Objekte, die FileParser beobachten, registrieren ihre Methoden mit den FileParser -Ereignissen in ihren Konstruktoren.

%Vor%

Danach geht das ParsedFileFrobber mit den Dingen ohne weitere explizite Interaktion aus.

Was mich stört, ist, dass das Hauptprogramm immer nur ein ParsedFileFrobber zuweist und sozusagen nicht den Rückgabewert des Konstruktors benutzt.

%Vor%

Es funktioniert, aber ReSharper beschwert sich darüber, was mich zumindest zum Nachdenken bewegt. Tatsächlich muss ich dem Ergebnis des Konstruktors nicht einmal eine Variable zuweisen, da der GC den ParsedFileFrobber durch die Verweise auf den Event-Handler am Leben erhält, aber ein bare new sieht für mich sehr falsch aus. (Es kompiliert und läuft immer noch korrekt.)

%Vor%

Ist das ein Problem? Ist es ein Anti-Pattern oder ein Code-Geruch? Gibt es bereits eine idiomatische Methode, dies in C # zu tun?

Danke!

Erläuterungen dank hilfreicher Kommentare:

1) Warum nicht die Beziehung invertieren? Cody Grey

Ah, das Beispiel war ein bisschen zu vereinfacht. Ich habe tatsächlich eine ParsedFileFrobber , eine ParsedFileGrobber und eine ParsedFileBrobber . Das Invertieren der Beziehung würde die FileParser von allen 3 abhängig machen. (Anfangs gab es nur einen Frobber und einen Grobber, aber später gab es einen Bedarf für einen Brobber, und es gibt immer noch Spielraum für uh, einen Drobber und so weiter.) Ich schätze, es ist eine Frage des Geschmacks, ob die Codezeilen, die die Subskription ausführen, im Konstruktor FileParser oder in den Konstruktoren ParsedFileFrobber , ParsedFileGrobber und ParsedFileBrobber vorkommen, aber ich möchte es versuchen die FileParser so agnostisch wie möglich zu halten.

2) Warum verschiebe ich den Konstruktor nicht in eine statische Methode (und mache den Konstruktor privat)? Hans Passant

Ich kann sehen, wie dies die möglicherweise nicht intuitive Nutzung in das private Innenleben der Klasse hineinräumt, was ein guter Rat ist. Es wäre jedoch immer noch entweder der bare new oder der einzige jemals zugewiesene Verweis auf den Rückgabewert des Konstruktors. Nun, wenn es kein großes Problem ist, ist es sinnvoll, den hässlichen Code zu verstecken. (Als Referenz habe ich die ParsedFileFrobber und IDisposable mit der Dispose -Methode gemacht, die sich von den Ereignissen abmeldet, so dass es möglich ist, dem Fröschen ein Ende zu setzen.)

Danke an alle Kommentatoren!

    
Ben O'Leary 30.11.2016, 08:54
quelle

2 Antworten

0
Am Ende ging ich mit etwas ähnlich dem, was Hans Passant empfahl: das nackte Neue in das innere Funktionieren einer statischen Methode aufzuräumen.

    
Ben O'Leary 19.03.2017, 14:57
quelle
1

Eine mögliche Lösung könnte sein, das Mediator-Muster zu verwenden, das eine neue Klasse einführt, die das Steuerelement steuert Interaktion zwischen Ihren FileParser und den ParsedFile* Klassen :. Auf diese Weise sind Ihre Klassen sehr lose gekoppelt, Ihre FileParser muss nicht über die ParsedFileFrobber wissen und umgekehrt. Die Mediator-Klasse kann auch auf die Lebensdauer der Objekte achten.

%Vor%

Eine andere Option könnte die Verwendung eines producer-consumer -Musters sein. So etwas wird z.B. von der TPL (Task Parallel Library) im .NET Framework. Sehen Sie sich den Abschnitt Datenfluss und die dort bereitgestellten Beispiele an.

    
Dirk Vollmar 30.11.2016 10:41
quelle