如何将依赖项注入模型?

时间:2017-04-27 00:27:17

标签: c# asp.net .net asp.net-mvc dependency-injection

通常,动作方法将以这样的结尾结束:

state1

但是如果我的模型要注入服务,它就不会有默认的ctor。所以它必须看起来像这样:

state2

但如果服务有依赖关系,那就更像是:

return View(new Model());

...开始变得荒谬。这不是IoC容器的用途吗?所以我很想写一些更像这样的东西:

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

但为了获得return View(new Model(new Service(new Repository()))); ,必须将其注入我的控制器,我听到injecting the container itself is an anti-pattern

那么正确的方法是什么?当我从action方法返回视图时,如何将依赖项传递给模型?

3 个答案:

答案 0 :(得分:1)

  

但是如果我的模型要注入服务

首先防止让您的视图模型具有依赖关系。视图模型应该是哑数据容器,并且应该在控制器操作返回时完全构造它们。这简化了视图和模型,并完全防止了这种情况。

如果您确实希望将依赖项传递给视图模型,则应该没有理由传递依赖项的依赖项。您只需要传入依赖项,并且由于您的控制器是一个应用程序组件,因此它会将该依赖项注入其构造函数中。所以它通常如下所示:

public class HomeController : Controller
{
    private readonly IService service;

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

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

由于DI容器将构建HomeController及其依赖关系(这意味着Service将使用Repository建立),您可以传递service 1}}依赖,而不必知道它的依赖性。

  

我听说注入容器本身就是一种反模式。

这是对的。使用Composition Root之外的Container是一个坏主意。

答案 1 :(得分:1)

你是对的。正确地执行依赖注入会使代码更清晰,但会添加执行注入和初始化的混乱代码。这就是DI框架到位的地方。它们的主要目标是处理与您类似的情况 - 删除混乱的构造函数注入代码而无需传递容器。使用像Ninject这样的DI框架,您的代码将如下所示:

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

这两篇文章中将显示您手动执行的操作与DI框架将执行的操作之间的对比:

顺便说一下,还有很多其他好的DI框架。你不需要服用Ninject,所有这些基本概念都是一样的。

答案 2 :(得分:0)

我使用了在引导程序代码中初始化的静态容器对象,但有时我不得不在容器中传递容器。有些代码闻到了,但想象一下有很多依赖的程序。但是如果你将DI与MVC一起使用,你就会自动注入容器,这就是我看到的模式(查看Autofac MVC)。