97 votes

Puis-je passer les paramètres du constructeur de l'Unité de la détermination du (des) méthode?

Je suis l'aide de Microsoft à l'Unité pour l'injection de dépendances et je veux faire quelque chose comme ceci:

  IDataContext context = _unityContainer.Resolve<IDataContext>();
  var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
  var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context

  IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
  var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);

RepositoryA et RepositoryB les deux ont un constructeur qui prend un IDataContext paramètre, et je veux l'Unité pour initialiser le référentiel avec le contexte que je le passe. Notez également que IDataContext n'est pas enregistré auprès de l'Unité (je ne veux pas 3 instances de IDataContext).

73voto

Exist Points 996

À compter d'aujourd'hui, ils ont ajouté cette fonctionnalité:

C'est dans la dernière baisse ici:

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

La Discussion sur le sujet ici:

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

Exemple:

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

39voto

Lasse V. Karlsen Points 148037

< 2 cents>

Que faire si vous plus tard décidez d'utiliser un autre service qui nécessite plus ou moins juste le contexte?

Le problème avec les paramètres du constructeur et de la Coi est que les paramètres sont en fin de compte lié au type de béton utilisé, par opposition à la partie du contrat que l'interface de service définit.

Ma suggestion serait que vous résoudre le contexte, et je crois que l'Unité doit avoir un moyen pour vous d'éviter de construire 3 instances de celui-ci, ou vous devriez envisager un service de l'usine qui a une façon pour vous de construire l'objet.

Par exemple, si vous avez plus tard décide de construire un référentiel qui ne repose pas sur une base de données traditionnelle, mais au lieu d'utiliser un fichier XML pour produire mannequin-données pour le test? Comment feriez-vous pour nourrir le contenu du fichier XML pour que le constructeur?

Cio est basé sur le découplage de code, en les liant dans le type et la sémantique des arguments pour les types de béton, vous vraiment n'avez 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, éventuellement, tant qu'il implémente cette interface.... Oh, et utilise un contexte de données".

Maintenant, je sais que d'autres Cio conteneurs disposent d'un soutien pour de cette, et je l'ai eu dans ma première version de mon propre bien, mais à mon avis, il n'appartient pas à l'étape de résolution.

< /2 cents>

4voto

Trecenti Points 61

Vous pouvez utiliser InjectionConstructor / InjectionProperty / InjectionMethod selon votre Injection de l'Architecture au sein de l'ResolvedParameter< T >("nom") pour obtenir une instance d'un pré-enregistré Objet dans le conteneur.

Dans votre cas, cet Objet doit être enregistré avec un Nom, et pour la même insance vous avez besoin ContainerControlledLifeTimeManager() comme le LifeTimeManager.

_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");

  var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));

3voto

Neil Hewitt Points 2163

La réponse courte est: non. L'unité dispose actuellement d'aucun moyen de passer des paramètres dans le constructeur qui ne sont pas constant ou injectée, que j'ai pu trouver. À mon humble avis c'est le seul truc qu'il en manque, mais je pense que c'est voulu par la conception plutôt que par omission.

Comme Jeff Fritz notes, vous pourriez en théorie de créer un personnalisé de durée de vie de manager qui sait quelle instance de contexte à injecter dans divers types, mais c'est un niveau de coder en dur qui semble écarter l'objectif de l'aide de l'Unité ou de la DI en premier lieu.

Vous pourriez faire un petit pas en arrière à partir de la pleine DI et faire de votre dépôt des implémentations responsable de l'établissement de leurs propres contextes. Le contexte de l'instance peut encore être résolu à partir du conteneur, mais la logique de choix dois aller dans la mise en œuvre du référentiel. Ce n'est pas aussi pur, certes, mais il serait de se débarrasser du problème.

1voto

Samuel Carrijo Points 9056

Une autre alternative, vous pouvez utiliser (ne sais pas vraiment si c'est une bonne pratique ou pas) est la création de deux conteneurs et l'enregistrement d'une instance pour chaque:

IDataContext context = _unityContainer.Resolve<IDataContext>();
_unityContainer.RegisterInstance(context);
var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context


//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance

espérons que cela aide aussi

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