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.
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.
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.)
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!
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.
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.
Tags und Links c# garbage-collection constructor events