Puis-je passer des parameters de constructeur à la méthode Resolve () d’Unity?

J’utilise l’Unité de Microsoft pour l’dependency injection et je veux faire quelque chose comme ceci:

IDataContext context = _unityContainer.Resolve(); var repositoryA = _unityContainer.Resolve(context); //Same instance of context var repositoryB = _unityContainer.Resolve(context); //Same instance of context IDataContext context2 = _unityContainer.Resolve(); //New instance var repositoryA2 = _unityContainer.Resolve(context2); 

RepositoryA et RepositoryB ont tous deux un constructeur qui prend un paramètre IDataContext , et je veux IDataContext initialise le référentiel avec le contexte que je lui transmets. Notez également que IDataContext n’est pas enregistré avec Unity (je ne veux pas 3 instances de IDataContext ).

A ce jour, ils ont ajouté cette fonctionnalité:

C’est dans la dernière goutte ici:

http://unity.codeplex.com/SourceControl/changeset/view/33899

Discussion ici:

http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434

Exemple:

 container.Resolve(new ParameterOverrides { { "name", "bar" }, { "address", 42 } });" 

<2 cents>

Et si vous décidiez plus tard d’utiliser un service différent nécessitant plus ou moins que le contexte?

Le problème avec les parameters de constructeur et IoC est que les parameters sont finalement liés au type de béton utilisé, au lieu de faire partie du contrat défini par l’interface de service.

Ma suggestion serait que vous résolviez également le contexte, et je crois qu’Unity devrait vous permettre d’en éviter 3, ou vous devriez envisager un service d’usine qui vous permettrait de construire l’object.

Par exemple, si vous décidiez plus tard de construire un référentiel qui ne repose pas du tout sur une firebase database traditionnelle, utilisez plutôt un fichier XML pour produire des données factices pour le test? Comment allez-vous alimenter le contenu XML à ce constructeur?

IoC est basé sur le découplage du code, en liant le type et la sémantique des arguments aux types concrets, vous n’avez vraiment pas fait le découplage correctement, il y a toujours une dépendance.

“Ce code peut parler à n’importe quel type de référentiel, à condition qu’il implémente cette interface … Oh, et utilise un contexte de données”.

Maintenant, je sais que d’autres conteneurs IoC ont un support pour cela, et je l’avais aussi dans ma première version, mais à mon avis, il n’appartient pas à l’étape de résolution.

Vous pouvez utiliser InjectionConstructor / InjectionProperty / InjectionMethod en fonction de votre architecture d’injection dans ResolvedParameter (“name”) pour obtenir une instance d’un object pré-enregistré dans le conteneur.

Dans votre cas, cet object doit être enregistré avec un nom et, pour la même insistance, vous avez besoin de ContainerControlledLifeTimeManager () en tant que LifeTimeManager.

 _unityContainer.RegisterType("DataContextA", new ContainerControlledLifeTimeManager()); _unityContainer.RegisterType("DataContextB"); var repositoryA = _unityContainer.Resolve(new InjectionConstructor( new ResolvedParameter("DataContextA"))); var repositoryB = _unityContainer.Resolve(new InjectionConstructor( new ResolvedParameter("DataContextA"))); var repositoryA2 = _unityContainer.Resolve(new InjectionConstructor( new ResolvedParameter("DataContextB"))); 

Merci les gars … le mien est similaire au poste de “Exist”. Voir ci-dessous:

  IUnityContainer container = new UnityContainer(); container.LoadConfiguration(); _activeDirectoryService = container.Resolve(new ResolverOverride[] { new ParameterOverride("activeDirectoryServer", "xyz.adserver.com") }); 

La réponse très courte est: non. Unity n’a actuellement aucun moyen de transmettre des parameters non constants ou injectés au constructeur, ce que j’ai pu trouver. À mon humble avis, c’est la plus grande chose qui manque, mais je pense que c’est par conception plutôt que par omission.

Comme le note Jeff Fritz, vous pouvez en théorie créer un gestionnaire de durée de vie personnalisé qui sait quelle instance de contexte injecter dans différents types, mais il s’agit d’un niveau de codage en dur qui semble éviter d’utiliser Unity ou DI.

Vous pourriez faire un petit pas en arrière par rapport à la DI complète et rendre vos implémentations de référentiel responsables de l’établissement de leurs propres contextes de données. L’ instance de contexte peut toujours être résolue à partir du conteneur, mais la logique permettant de décider lequel utiliser doit entrer dans l’implémentation du référentiel. Ce n’est pas aussi pur, certes, mais cela éliminerait le problème.

Une autre alternative que vous pourriez utiliser (ne sais pas vraiment si c’est une bonne pratique ou non) est de créer deux conteneurs et d’enregistrer une instance pour chacun:

 IDataContext context = _unityContainer.Resolve(); _unityContainer.RegisterInstance(context); var repositoryA = _unityContainer.Resolve(); //Same instance of context var repositoryB = _unityContainer.Resolve(); //Same instance of context //declare _unityContainer2 IDataContext context2 = _unityContainer2.Resolve(); //New instance _unityContainer2.RegisterInstance(context2); var repositoryA2 = _unityContainer2.Resolve(context2); //will resortingeve the other instance 

espère que cela aide aussi

NotDan, je pense que vous avez peut-être répondu à votre propre question dans les commentaires à lassevk.

Premièrement, j’utiliserais un LifetimeManager pour gérer le cycle de vie et le nombre d’instances d’IDataContext créés par Unity.
http://msdn.microsoft.com/en-us/library/cc440953.aspx

Il semble que l’object ContainerControlledLifetimeManager vous fournira la gestion d’instance dont vous avez besoin. Avec ce LifetimeManager en place, Unity devrait append la même instance de IDataContext à tous les objects nécessitant une dépendance IDataContext.