En ce moment, nous utilisons DI / IOC et lorsque nous devons passer des paramètres supplémentaires à un constructeur, nous utilisons une classe d'usine, par exemple
public class EmailSender { public class Factory { ILogger emailLogger; public Factory(ILogger emailLogger) { this.emailLogger = emailLogger; } public EmailSender Create(string toEmail, string subject, string body) { return new EmailSender(toEmail, subject, body, emailLogger); } } private EmailSender(string toEmail, string subject,String body, ILogger emailLogger) { } }
3 Réponses :
oui - c'est mauvais. p>
Un autre aspect encore plus important, est que vos composants sont liés à votre localisateur de services. P>
Vous êtes maintenant incapable de les instantiez comme ça - tu as besoin d'un Complètement configurez le localisateur de services dans placer chaque fois que vous devez utiliser un composant. p> li>
L'écriture 'x = ioc.Resolve
Vous n'avez pas à écrire des cours d'usine! Conteneur IOC est un seul configurable UberFactory et si vous structurez correctement votre code, tout ce dont vous avez besoin.
Et vous souhaitez tirer des services de certaines usines vous-même (et vous utilisez Windsor), vous pouvez toujours utiliser une installation TypeFactory qui mettra en œuvre votre usine sauvegardée par le conteneur CastleProject.org/Container/facitiers/v1rc3/typedFactory/... ou autogène CODE.GOOGE.COM/P/castleAutogen
Dans la situation détaillée ci-dessus, vous avez des paramètres qui doivent être transmis au temps de création (corps, à, sujet). Sans une classe d'usine explicite, vous vous retrouvez avec des chaînes magiques comme noms de paramètres.
Que vous pouvez utiliser les installations que je vous ai donné des liens ci-dessus. Cependant, je pense que tu le fais mal. J'aurais juste avoir un corps d'Iemailervice et passer du corps, sous réserve de paramètre à sa méthode i>, laissant les détails de la mise en œuvre encapsulés, sa mise en œuvre est gratuite pour nouveau dans le courrier électronique ou tout ce qui est nécessaire à l'intérieur, et I En tant qu'utilisateur, je suis blindé de ces détails de mise en œuvre. De plus, je n'ai besoin d'aucune usine pour le faire, profiter des avantages de l'inversion du contrôle
Dans ce cas, je suggère que vous suggère de ressembler beaucoup à une usine pour moi! L'exemple ci-dessus était destiné à être représentatif d'une classe immuable de quelque nature que ce soit, nécessite des paramètres du constructeur. Ma question, plus précise est retraitée, devient "dans la situation que vous avez une classe immuable, qui prend des paramètres non connus tant que le temps de création et certains qui sont enregistrés dans un conteneur DI, et que vous ne voulez pas avoir de chaînes magiques dans CodeBase *, est-il correct d'utiliser des appels en ligne vers un SL pour éviter les coûts d'écriture des usines ". * A par produit d'usines de réception automatique
et bien non. Je pense toujours que c'est un problème avec votre conception. Pouvez-vous montrer plus de scénario de vie réel? Pourquoi avez-vous besoin de cette classe pour être immuable? Emainservices.Sendemail (Toemail, Sujet, Corps); <- C'est comme ça que je le ferais. Pas besoin de SL ici.
Peut-être que chacun des courriels est une entité et je dois persister ce que j'ai envoyé à des fins de rapport? Je pense que nous avons passé un peu loin avec cette discussion, je pense que je devrais arrêter de poster des QS théoriques!
Oui, nous dérivons :) Quoi qu'il en soit, il est généralement possible (et préféré) de s'efforcer d'atteindre l'indépendance SL. Dans votre échantillon, je ne voudrais certainement pas persister mon message électronique au même endroit qui l'envoie! De toute façon bonne chance :)
La principale raison pour laquelle je puisse penser (sans simplement regarder des problèmes avec les localisateurs de services en général) est que ce n'est pas ce que j'appuie un utilisateur de votre classe Attendez-vous à . p>
Discussion Meta:
Quelques cadences de DI ( Guice par exemple) Construisez l'usine pour vous . p>
Certaines personnes Avocat A > Séparer le "nouveau" de l'injectable ". p>
@MLK: Je viens de remarquer votre lien "nouveau" après avoir commenté la question initiale. +1 pour cela très intéressant. Donc, pour le scénario spécifique de l'OP, classeriez-vous cela comme une "nouvelle" "plutôt que" injectable ", et donc inutile ou incapable d'utiliser di?
Je ne vais pas vraiment avec l'ensemble "injectant une bûche". Je verrais comme un travail d'AOP ou de saisir simplement de l'usine fournie par le cadre d'exploitation forestière. Les coutures emailsends comme une classe étrange pour moi. Je verrais probablement cela comme deux classes, EmailMessage - une nouvelle et des e-mails - une injectable.
Je ne suis pas tout à fait sûr de ce fort "c'est mauvais" réponse donnée par Krzysztof. Je pense qu'il y a un peu de compromis et de préférence là-bas sans les classer absolument comme mauvais ou bon. P>
Je pense que l'utilisation d'un localisateur de services cachent effectivement vos dépendances à l'intérieur de la classe au lieu de les exposer à travers des constructeurs. Et c'est un inconvénient à mon avis parce que vous ne saurez pas que votre classe manque quelque chose jusqu'à ce que le localisateur de services soit appelé sans être configuré. P>
Mais la chose di chose n'est pas libre de ce genre de noir de l'obscurité. Lorsque vous utilisez DI, il n'est vraiment pas évident de comprendre comment ces dépendances ne sont que «apparues» (DI Magic) dans votre constructeur. En utilisant un SL, vous pouvez au moins voir où ces dépendances viennent. P>
Mais toujours, lorsque vous testez une classe qui expose ces dépendances sur ses constructeurs, vous ne pouvez pas le manquer. Ce n'est pas le cas à l'aide d'un localisateur de service. P>
Je ne dis pas que Krzysztof était faux, car je suis d'accord avec lui pour le plus. Mais je suis sûr que l'utilisation d'un localisateur de service n'est pas nécessairement une mauvaise "conception" et certainement pas tout simplement mal. P>
phil p>
Lorsque vous regardez cela du point de vue de la migration d'une base de code héritée vers (éventuellement) à l'aide de DI, il s'agit peut-être d'un outil (temporaire) qui peut être utilisé en cours de route?
Merci d'avoir posté des modifications, je trouve ce processus de pensée très utile car je pense à travers les mêmes défis.
C'est une excellente question et une excellente question que je ne pense pas a été vraiment répondue correctement ci-dessous. Peut-être que je manque quelque chose, mais je n'ai vu que des solutions qui vous permettent de définir des paramètres de constructeur supplémentaires de manière centralisée de manière centralisée de manière centralisée que la résolution des interfaces de manière centralisée est effectuée. C'est une situation très différente de celle décrite ci-dessus, où vous souhaitez pouvoir utiliser le CTOR avec des paramètres comme d'habitude, mais profitez également de découpler l'objet ILogger. Je ne peux que supposer que ce type d'utilisation rend ces scénarios inappropriés pour DI avec CTORS.
J'ai l'impression que la forme DI de CIO devrait vraiment être réservée aux véritables "composants de service" qui ne nécessitent pas de configuration dans la manière dont vous souhaitez le faire ci-dessus. Cela dit, je serais ravi d'être montré autrement! :)