La sérialisation empêche-t-elle l'utilisation de l'injection de dépendance?

9

Question simple: je comprends que la sérialisation en C # nécessite des constructeurs par défaut. Cela éliminerait la possibilité d'utiliser DI injecteur constructeur (qui est généralement le style préféré de DI, dans ma lecture [citation nécessaire] ). Alors, est-ce vraiment une situation ou, ou manque-t-il quelque chose?

(Question secondaire): Les conteneurs IoC annulent-ils en quelque sorte ce compromis?

kmote
la source
This would eliminate the possibility of using Constructor injected DI-- Pourquoi? Vous pouvez toujours avoir des instructeurs paramétrés, tant que vous incluez un constructeur par défaut à des fins de sérialisation (le constructeur par défaut peut être privé, si vous le souhaitez).
Robert Harvey
@RobertHarvey: Je me sens un peu dense, mais je ne comprends pas très bien. Qu'est-ce qu'un "instructeur paramétré"? (faute de frappe?) Une fois qu'un objet a été désérialisé, je ne peux pas le reconstruire. Suggérez-vous que j'utilise l'injection de propriété / setter sur un objet construit par défaut?
kmote
1
Un constructeur paramétré est un constructeur avec des paramètres. Je suppose ici que la désérialisation se produit à partir de données dérivées d'un objet correctement construit à l'aide de l'injection de dépendance. Vous n'avez pas besoin de construire l'objet pendant la désérialisation; il a déjà été construit auparavant.
Robert Harvey
1
Non, vous ne vous trompez pas. Voilà comment ça marche. Considérez-le comme une injection par derrière. Vous n'obtiendrez aucune validation, mais cela fonctionnera. Notez que BinaryFormatter et DataContractSerializer ne nécessitent pas de constructeurs par défaut.
Robert Harvey
1
Pour être clair, la désérialisation ne fait que remplir l'état de votre objet avec les valeurs spécifiées dans l'objet XML. Il utilise Reflection pour accomplir cela et contourne toute forme de logique de validation de constructeur, donc du point de vue de DI, il triche, à moins que ces valeurs XML proviennent à l'origine d'un objet construit via DI ordinaire.
Robert Harvey

Réponses:

6

Il n'est pas possible de désérialiser un objet et d'injecter également une dépendance à un autre objet déjà existant, en une seule étape en C #, en utilisant les mécanismes de sérialisation standard. Vous devrez utiliser l'injection de propriété à la place, en construisant d'abord l'objet à l'aide du désérialiseur, puis en injectant la dépendance. Pour la plupart des applications du monde réel, je ne considère pas cela comme un véritable inconvénient - si vous avez une classe de modèle de données sérialisable, qui a également des dépendances avec d'autres classes de modèle non-données, vous devez vérifier si votre classe de modèle de données peut avoir trop de responsabilités déjà.

Si cela vous dérange vraiment, vous pouvez envisager d'encapsuler votre objet sérialisable avec une classe décoratrice, où vous pouvez passer le désérialiseur et les dépendances supplémentaires via le constructeur. Ce wrapper exécute ensuite les deux étapes (désérialisation de l'objet encapsulé et injection de propriété) dans son constructeur.

Doc Brown
la source
1

Je résous ce problème comme ça: injecter des usines de dépendances. Dans ces usines, résolvez d'abord la dépendance telle qu'elle est enregistrée dans le conteneur, puis "désérialisez" toutes les données restantes: json.net permet de remplir les champs de l'objet existant.

Comme le code des usines va de pair avec le code de câblage du conteneur IoC, je ne pense pas que l'utilisation à l' container.Resolveintérieur de l'usine viole la règle, qui containerdoit être utilisée à un seul endroit dans le code: où tout le câblage se produit.

À partir de maintenant, j'essaie de rendre ce processus automatique (par opposition à ce que j'ai testé cette approche) en utilisant la réflexion. Oui, il ne reste pas grand-chose de la désérialisation de json.net elle-même, une partie est remplacée par du code personnalisé, mais je pense, pourquoi s'embêter.

En outre, quelles ont été vos dernières réflexions / décisions sur la question? Après avoir lu ce post, je vois deux façons: désérialiser, puis injecter; ou injecter, puis désérialiser (remplir). Et je trouve toujours que mon chemin est meilleur. Je serai heureux d'entendre des arguments en opposition à cela (je pense que ma voie peut être meilleure pour mon cas, mais je ne peux pas imaginer de manière vivante de bons cas alternatifs, où cela échoue, juste quelques suppositions mineures)

jungle_mole
la source