Question

(à partir du fichier StockTraderRIBootstrapper.cs dans StockTrader Prism V2 exemple d'application)

Quelle est la différence entre ceci:

ShellPresenter presenter = new ShellPresenter();

et ceci:

ShellPresenter presenter = Container.Resolve<ShellPresenter>();
  • Je crois comprendre que le deuxième exemple consiste à traiter le conteneur comme une usine et à lui dire: «J'ai besoin d’un objet instancié de type ShellPresenter».
  • Mais si, par exemple, J'ai besoin d'envoyer des paramètres, ce qui serait l'équivalent de "new ShellPresenter (1, true)" etc.?
  • Et comme le conteneur doit être renseigné sur ShellPresenter, je m'attendais à trouver quelque part dans le projet un endroit où la classe ShellPresenter est enregistrée avec le conteneur, par exemple. Je m'attendais

quelque chose comme ceci:

Container.RegisterType<IShellPresenter, ShellPresenter>();

mais je ne l'ai trouvé nulle part. Alors, comment le conteneur peut-il connaître ces types afin de pouvoir les résoudre? Je l'ai reconstruite dans son propre projet et j'obtiens une "résolution de la dépendance a échoué". erreur , où dois-je alors enregistrer cette dépendance?

Toute orientation / discussion ici serait utile.

Réponse inexpliquée:

Ainsi, dans le programme d'amorçage, lorsque j'enregistre le shell lui-même:

protected override void ConfigureContainer()
{
    Container.RegisterType<IShellView, Shell>();
    base.ConfigureContainer();
}

alors le conteneur peut résoudre le type ShellPresenter. Comment le type ShellPresenter est-il enregistré lorsque j'enregistre le type Shell ?

La réponse surprenante:

Ok, il s'avère donc que vous n'avez pas besoin d'enregistrer le type que vous essayez de résoudre, mais vous devez enregistrer les types de paramètre (interface) transmis au constructeur du type que vous essayez d'utiliser. résoudre , c’est-à-dire que puisque j’injecte l’interface IShellView dans le constructeur de mon fournisseur, il me fallait enregistrer le type IShellView et non le type IShellPresenter:

public ShellPresenter(IShellView view) ...

J'ai testé cela en essayant de résoudre le type Testeur :

Tester tester = Container.Resolve<Tester>();

Tant que j'injecte SomeClass dans son constructeur:

public Tester(ISomeClass someClass)

J'obtiens des erreurs de dépendance non résolues jusqu'à ce que j'enregistre SomeClass dans le conteneur:

Container.RegisterType<ISomeClass, SomeClass>();

Ensuite, ça marche. C'est aussi surprenant qu'éducatif. Je dois aller prendre un café et y réfléchir pendant un moment.

Si quelqu'un peut expliquer pourquoi c'est le cas, ce serait très apprécié.

Était-ce utile?

La solution

Vous comprenez les bases.

Il existe des surcharges pour la résolution des types nécessitant des arguments de constructeur. Sinon, vous pouvez toujours coder vos types pour avoir un constructeur sans paramètre.

Le point essentiel des conteneurs DI est que vous pouvez les configurer pour modifier le type à résoudre pour une interface particulière sans recompiler votre logiciel. L'exemple de code que vous avez fourni pour configurer le fournisseur ne peut pas être modifié au moment de l'exécution. C'est pourquoi la plupart des injecteurs de dépendance vous permettent de les configurer dans app.config / web.config / un autre fichier de configuration externe. De cette façon, vous pouvez reconfigurer votre application pour injecter un type différent sans recompiler, ce qui est le véritable pouvoir des frameworks DI comme Unity.

Autres conseils

Si vous essayez de résoudre une classe concrète sans avoir enregistré une instance ou une sous-classe pour la satisfaire, alors Unity construira une instance de la classe concrète pour vous, en résolvant ses dépendances éventuelles.

Ainsi, lorsque vous demandez ShellPresenter et que vous ne l'avez pas enregistré, Unity vient juste de créer un ShellPresenter pour vous avec ShellView en tant que paramètre.

Eh bien, je ne peux pas répondre pour Untiy, mais pour Castle Windsor, l'enregistrement pourrait se trouver dans le fichier app.config / web.config. Il est également possible d’ajouter les paramètres dans le fichier XML de config.

Ceci vous permet de modifier l'implémentation et la configuration de l'objet sans avoir à recompiler votre application.

Dans Unity, il existe effectivement un ensemble de méthodes Container.RegisterType < TFrom, TTo > () qui enregistre les types à l'exécution. Il est probablement plus courant de le faire en utilisant un fichier de configuration XML, mais cela fonctionne.

Fait intéressant, dans Unity, il n’existe pas de méthode Container.Resolve < T > (params object [] parameters) pour résoudre un type avec des valeurs de paramètre de constructeur spécifiques. Unity est construit sur ObjectBuilder, qui est la bibliothèque de l’équipe P & amp; P pour la construction et le câblage d’objets (IIRC a été écrit à l’origine pour ObjectSpaces mais a été considérablement amélioré). ObjectBuilder vous permet d'injecter des dépendances de différentes manières, y compris via le constructeur. Ainsi, vous pourriez par exemple indiquer que vous transmettriez une nouvelle instance d'un type dont il dépend au constructeur d'un type résolu; mais ce type devrait aussi être enregistré. Vous pouvez également transmettre des instances de types enregistrés (une instance enregistrée / singleton, etc.). Mais AFAICS, il n’ya aucun moyen de simplement lui donner une valeur à transmettre.

Je pense que cela irait à l'encontre de la philosophie d'IoC dans une certaine mesure, c'est pourquoi ils ne fournissent pas cette installation. Le conteneur devrait, en théorie, pouvoir vous donner un graphe d'objet complet dans n'importe quelle circonstance. Vous ne devriez donc jamais avoir à passer de paramètres et rendre vos objets dépendants de paramètres de constructeur autres que les dépendances d'objet injectables (que le conteneur va résoudre pour vous) est considéré comme un mauvais design.

Je ne peux pas parler pour Windsor, StructureMap ou les autres, ce qui peut vous permettre de le faire. Je ne peux même pas affirmer catégoriquement qu'Unity n'a aucun moyen de le faire car je suis assez novice dans ce domaine, mais Chris Tavares du IIRC, qui a essentiellement construit Unity, traîne ici de temps en temps, alors peut-être qu'il passera répondez à celle-ci: -)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top