18 votes

Que signifie cela dans Prism/Unity : Container.Resolve<ShellPresenter>()

(depuis le fichier StockTraderRIBootstrapper.cs dans l'exemple d'application StockTrader Prism V2)

Quelle est la différence entre ceci :

ShellPresenter presenter = new ShellPresenter();

et ceci :

ShellPresenter presenter = Container.Resolve();
  • Je comprends que le deuxième exemple traite le conteneur comme une usine, allant vers lui en disant "J'ai besoin d'un objet instancié de type ShellPresenter".
  • Mais que se passe-t-il si, par exemple, j'ai besoin d'envoyer des paramètres, quelle serait l'équivalent de "new ShellPresenter(1, true)" etc.?
  • Et étant donné que le Container doit être informé au sujet de 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();

mais je ne l'ai trouvé nulle part. Comment le conteneur apprend-t-il à propos de ces types pour pouvoir les .Resolve ? J'ai reconstruit ceci dans son propre projet et j'obtiens une erreur "Resolution of the dependency failed", où dois-je enregistrer cette dépendance alors ?

Toute direction/discussion ici serait utile.

Réponse Inexpliquée :

Ainsi, dans le bootstrapper, lorsque j'enregistre le Shell lui-même :

protected override void ConfigureContainer()
{
    Container.RegisterType();
    base.ConfigureContainer();
}

ensuite, 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 :

D'accord, il s'avère que vous n'avez pas besoin d'enregistrer le type que vous essayez de résoudre mais vous devez enregistrer les types de paramètres (interfaces) passés au constructeur du type que vous essayez de résoudre, c'est-à-dire que puisque j'injecte l'interface IShellView dans le constructeur de mon ShellPresenter, j'ai dû enregistrer le type IShellView et non le type IShellPresenter :

public ShellPresenter(IShellView view) ...

J'ai testé ceci en essayant de résoudre le type Tester :

Tester tester = Container.Resolve();

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 avec le conteneur :

Container.RegisterType();

Ensuite, ça fonctionne. C'est aussi surprenant qu'éducatif. Cela doit rentrer. Je vais prendre un café et réfléchir à cela pendant un moment.

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

12voto

Ray Henry Points 716

Si vous essayez de résoudre une classe concrète et que vous n'avez pas 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 toutes les dépendances qu'elle a.

Donc, lorsque vous demandez ShellPresenter, et que vous ne l'avez pas enregistré, Unity crée simplement un nouveau ShellPresenter pour vous avec ShellView en tant que paramètre.

6voto

Will Points 76760

Vous comprenez les bases.

Il existe des surcharges pour résoudre les types qui nécessitent des arguments de constructeur. Alternativement, vous pouvez toujours coder vos types pour avoir un constructeur sans paramètres.

Le point des conteneurs d'injection de dépendances est que vous pouvez les configurer pour changer le type qui est résolu 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é à l'exécution. C'est pourquoi la plupart des injecteurs de dépendances vous permettent de les configurer dans un fichier de configuration externe tel que app.config/web.config/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 d'injection de dépendances comme Unity.

1voto

James Curran Points 55356

Eh bien, je ne peux pas répondre pour Untiy, mais pour Castle Windsor, l'inscription pourrait être dans le fichier app.config/web.config. Il est également possible d'ajouter les paramètres dans le xml de configuration.

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

1voto

Neil Hewitt Points 2163

À Unity, il existe en effet une méthode Container.RegisterType() qui enregistre les types à l'exécution. Il est probablement plus courant de le faire en utilisant un fichier de configuration XML, mais les deux méthodes fonctionnent.

Curieusement, Unity ne propose pas de méthode de type Container.Resolve(params object[] parameters) pour résoudre un type avec des valeurs de paramètres de constructeur spécifiques. Unity est basé sur ObjectBuilder, qui est la bibliothèque de l'équipe P&P pour la construction et le câblage d'objets (si je me souviens bien, elle a été initialement écrite pour ObjectSpaces mais a été considérablement améliorée depuis). ObjectBuilder vous donne la possibilité d'injecter des dépendances de différentes manières, y compris via le constructeur, de sorte que vous pourriez dire - par exemple - que vous transmettriez une nouvelle instance d'un type sur lequel il dépend dans le constructeur d'un type résolu ; mais ce type devrait également être enregistré. Vous pouvez également transmettre des instances de types enregistrés (une instance enregistrée / singleton, etc.). Mais à ma connaissance, il n'y a aucun moyen de simplement lui donner une valeur à transmettre.

Je pense que faire cela irait à l'encontre de la philosophie de l'IoC dans une certaine mesure, c'est pourquoi ils ne fournissent pas cette fonctionnalité. Le conteneur devrait, en théorie, être capable de vous fournir un graphe d'objets complet dans toutes les circonstances, vous ne devriez donc jamais avoir à transmettre des paramètres, et rendre vos objets dépendants de paramètres de constructeur autres que les dépendances d'objets injectables (que le conteneur résoudra pour vous) est considéré comme une mauvaise conception.

Je ne peux pas parler pour Windsor, StructureMap ou les autres, qui peuvent vous permettre de le faire. Je ne peux même pas dire catégoriquement qu'Unity n'a aucun moyen de le faire car je suis relativement nouveau, mais si je me souviens bien, Chris Tavares - qui a essentiellement construit Unity - passe par ici de temps en temps, donc peut-être qu'il viendra répondre à cela :-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X