2017-04-27 1 views
0

En règle générale, une méthode d'action se termine par quelque chose comme ceci:Comment injecter des dépendances dans un modèle?

return View(new Model()); 

Mais si mon modèle va avoir des services injectés, il ne sera pas un cteur par défaut. Il faudrait donc ressembler à ceci:

return View(new Model(new Service()); 

Mais si le service a des dépendances, il serait plus comme ceci:

return View(new Model(new Service(new Repository()))); 

... qui commence à se ridicule. N'est-ce pas à quoi sert un conteneur IoC? Donc, je serais tenté d'écrire quelque chose comme ceci:

return View(container.Resolve<IModel>()); 

mais afin d'obtenir container il faudrait injecter dans mon contrôleur, et j'entends que injecting the container itself is an anti-pattern.

Alors, quelle est la bonne façon? Comment transmettre mes dépendances à mon modèle lorsque je renvoie la vue depuis la méthode d'action?

Répondre

0

J'ai utilisé un objet conteneur statique initialisé dans le code d'amorçage, mais parfois j'ai dû passer le conteneur dans un paramètre. Un peu de code, mais imaginez une procédure avec beaucoup de dépendances. Mais si vous utilisez DI avec MVC, vous obtenez le conteneur injecté automatiquement, et c'est le modèle que je vois (consultez Autofac MVC).

1

Mais si mon modèle va avoir des services

injecté

Prévenir laisser vos modèles vue d'avoir des dépendances en premier lieu. Les modèles de vue doivent être des conteneurs de données muets et ils doivent être entièrement construits lorsque l'action du contrôleur revient. Cela simplifie la vue et le modèle et empêche complètement la situation.

Dans le cas où vous voulez vraiment transmettre des dépendances au modèle de vue, il ne devrait y avoir aucune raison de transmettre les dépendances d'une dépendance. Vous n'avez qu'à transmettre la dépendance, et puisque votre contrôleur est un composant d'application, cette dépendance sera injectée dans son constructeur. Ainsi, il sera généralement se présenter comme suit:

public class HomeController : Controller 
{ 
    private readonly IService service; 

    public HomeController(IService service) 
    { 
     this.service = service; 
    } 

    public ViewResult Index() 
    { 
     return View(new Model(this.service)); 
    } 
} 

Depuis HomeController sera intégré par le conteneur DI avec ses dépendances (ce qui signifie Service sera intégré à l'aide Repository), vous pouvez simplement passer sur la dépendance service sans avoir à connaître quoi que ce soit sur sa dépendance.

et j'entends que l'injection du conteneur lui-même est un anti-modèle.

C'est correct. L'utilisation du Container en dehors du Composition Root est une mauvaise idée.

1

Vous avez raison. Si vous effectuez correctement l'injection de dépendances, votre code est plus propre, mais vous ajoutez du code encombré qui effectue l'injection et l'initialisation. C'est là que les cadres de DI sont mis en place. Leur objectif principal est de gérer exactement les situations comme la vôtre - supprimer le code d'injection du constructeur encombré sans avoir à passer le long du conteneur.Avec un cadre de DI comme Ninject votre code ressemblerait à ceci:

IKernel kernel = new StandardKernel(); 
Bind<View>(); 
Bind<Model>(); 
Bind<Service>(); 
Bind<Repository>(); 
var view = kernel.Get<View>(); 

Le contraste entre ce que vous feriez manuellement et quel cadre DI ferait est montré dans ces deux articles:

BTW il existe de nombreux autres bons cadres DI autour. Vous n'avez pas besoin de prendre Ninject, l'idée de base est la même.