Schließt die Serialisierung die Verwendung der Abhängigkeitsinjektion aus?

9

Einfache Frage: Ich verstehe, dass für die Serialisierung in C # Standardkonstruktoren erforderlich sind. Dies würde die Möglichkeit der Verwendung von Konstruktor-injiziertem DI ausschließen (was in meiner Lektüre im Allgemeinen der bevorzugte DI-Stil ist [Zitieren erforderlich] ). Ist es also wirklich eine Entweder-Oder-Situation oder fehlt mir etwas?

(Nebenfrage): Gehen IoC-Container irgendwie von diesem Kompromiss ab?

kmote
quelle
This would eliminate the possibility of using Constructor injected DI-- Warum? Sie können weiterhin parametrisierte Instruktoren haben, solange Sie einen Standardkonstruktor für Serialisierungszwecke einschließen (der Standardkonstruktor kann privat sein, wenn Sie möchten).
Robert Harvey
@ RobertHarvey: Ich fühle mich ein bisschen dicht, aber ich verstehe dich nicht ganz. Was ist ein "parametrisierter Instruktor"? (Tippfehler?) Sobald ein Objekt de-serialisiert wurde, kann ich es nicht mehr erstellen. Schlagen Sie vor, dass ich die Eigenschafts- / Setter-Injektion für ein standardmäßig erstelltes Objekt verwende?
kmote
1
Ein parametrisierter Konstruktor ist einer mit Parametern. Ich gehe hier davon aus, dass die Deserialisierung aus Daten erfolgt, die von einem Objekt abgeleitet wurden, das mithilfe der Abhängigkeitsinjektion ordnungsgemäß erstellt wurde. Sie müssen das Objekt während der Deserialisierung nicht erstellen. es wurde schon vorher gebaut.
Robert Harvey
1
Nein, du liegst nicht falsch. So funktioniert das. Betrachten Sie es als Hintertürspritze. Sie erhalten keine Validierung, aber es wird funktionieren. Beachten Sie, dass für BinaryFormatter und DataContractSerializer keine Standardkonstruktoren erforderlich sind.
Robert Harvey
1
Um klar zu sein, füllt die Deserialisierung lediglich den Status in Ihrem Objekt mit den Werten, die im XML-Objekt angegeben sind. Es verwendet Reflection, um dies zu erreichen, und umgeht jede Form von Konstruktorvalidierungslogik. Aus Sicht von DI betrügt es also, es sei denn, diese XML-Werte stammen ursprünglich von einem Objekt, das durch gewöhnliches DI erstellt wurde.
Robert Harvey

Antworten:

6

Es ist nicht möglich, ein Objekt in einem Schritt in C # mithilfe der Standard-Serialisierungsmechanismen zu de-serialisieren und eine Abhängigkeit in ein anderes, bereits vorhandenes Objekt einzufügen. Sie müssen stattdessen die Eigenschaftsinjektion verwenden, indem Sie zuerst das Objekt mit dem Deserializer erstellen und anschließend die Abhängigkeit injizieren. Für die meisten realen Anwendungen halte ich dies nicht für einen echten Nachteil. Wenn Sie eine serialisierbare Datenmodellklasse haben, die auch Abhängigkeiten zu anderen Nicht-Datenmodellklassen aufweist, sollten Sie prüfen, ob Ihre Datenmodellklasse möglicherweise über einen solchen Nachteil verfügt schon zu viele Verantwortlichkeiten.

Wenn Sie das wirklich stört, können Sie Ihr serialisierbares Objekt mit einer Decorator-Klasse umschließen, in der Sie den De-Serializer und zusätzliche Abhängigkeiten durch den Konstruktor übergeben können. Dieser Wrapper führt dann die beiden Schritte (De-Serialisierung des umschlossenen Objekts und Eigenschaftsinjektion) in seinem Konstruktor aus.

Doc Brown
quelle
1

Ich löse dieses Problem so: Injizieren von Abhängigkeitsfabriken. Lösen Sie in diesen Fabriken zuerst die Abhängigkeit auf, wenn sie im Container registriert ist, und "deserialisieren" Sie dann alle verbleibenden Daten: json.net ermöglicht das Auffüllen von Feldern in vorhandenen Objekten.

Da der Fabrikcode mit dem Verdrahtungscode des IoC-Containers einhergeht, container.Resolveverstößt die Verwendung innerhalb der Fabrik meiner Meinung nach nicht gegen die Regel, containerdie nur an einer Stelle im Code verwendet werden muss: wo die gesamte Verdrahtung stattfindet.

Ab sofort versuche ich, diesen Prozess mithilfe von Reflexion automatisch zu gestalten (im Gegensatz zu dem, bei dem ich diesen Ansatz getestet habe). Ja, es bleibt nicht viel von der Deserialisierung von json.net selbst übrig. Ein Teil davon wird durch benutzerdefinierten Code ersetzt, aber ich denke, warum sollte man sich darum kümmern?

Was waren Ihre letzten Gedanken / Entscheidungen in dieser Angelegenheit? Nachdem ich diesen Beitrag gelesen habe, sehe ich zwei Möglichkeiten: deserialisieren, dann injizieren; oder injizieren, dann deserialisieren (bevölkern). Und ich finde immer noch, dass mein Weg besser ist. Ich werde mich freuen, Argumente dagegen zu hören (ich bin der Meinung, dass mein Weg für meinen Fall vielleicht besser ist, kann mir aber keine guten alternativen Fälle vorstellen, in denen dies fehlschlägt, nur ein paar kleine Vermutungen).

jungle_mole
quelle