在控制器中实现依赖注入以创建松耦合系统

时间:2012-07-25 08:33:03

标签: asp.net-mvc asp.net-mvc-3 dependency-injection unity-container

我有一个HomeController和一个类型类的引用。如果我创建了一个类的新对象,它对我来说很好。但我不想在Controller中创建新对象,而是想通过HomwController的Constructor传递类的引用。这是我的代码。我需要在这里实施DI。

//private readonly UnitOfWork<Student> _unitOfWork = new UnitOfWork<Student>();
    private readonly UnitOfWork<Student> _unitOfWork;

    //TODO ??
    public HomeController(UnitOfWork<Student> unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public ActionResult Index()
    {


        return View(_unitOfWork.GenericRepository.GetAll());
    }

任何帮助?

2 个答案:

答案 0 :(得分:2)

首先,如果你想使用依赖注入,你将不得不通过第三方依赖注入容器 - 例如NInject或Unity等许多其他容器(如果你正在寻找一些挑战,那么建立你自己的容器)。 / p>

其次,您的HomeController应该将抽象的工作单元类型(接口或抽象类)作为参数。实际上,你在HomeController构造函数中使用了一个具体的类型,而不是在依赖注入世界中应该如何工作(当使用“构造函数注入”时,你的依赖容器负责根据容器配置提供抽象的具体实现。 )。

你的UnitOfWork<Student>第三个没有多大意义。 Repository<Student>会有所帮助,但是工作单元不是在单个“类型”上工作,而是在不同数据集的“集合”上工作(一个工作单元可能在一组存储库上工作) 。这里有意义的是在HomeController构造函数中指定参数IUnitOfWork unitOfWork,并配置您的依赖项容器以传递一个具体的UnitOfWork对象,您可以在该对象上执行Repository<Student>操作它在您的操作方法中(可能在从UnitOfWork对象访问的其他存储库中),然后通过调用UnitOfWork对象上的关联方法来提交所有修改。

你应该在NInject中使用ASP.NET MVC3进行一些搜索,如果你正在处理UnitOfWork和Repository模式(如果数据是由数据库支持的话),还应该看一下EntityFramework。

修改

对您处理(IUnitOfWork<Student>IUnitOfWork<Course>)的评论作出回应。

正如我之前所说,它没有多大意义:

UnitOfWork可以被视为存储库的“容器”,可以访问这些存储库并协调这些存储库上的操作(如提交所有更改)。您应该使用抽象的非泛型类型IUnitOfWork,提供对IRepository<Student>IRepository<Course>等通用存储库的访问,并且还包含将提交到DB(或文件,或者内存或任何单元工作/存储库实现的目标是持久化数据。)

这样,而不是在控制器构造函数中注入IRepository<Student>和/或IRepository<Course>(或者如果你的控制器需要在10个不同的存储库上工作,那么,传递10个参数:S),你只需要接受抽象类型IUnitOfWork的单个参数(由DI容器注入的具体实例),然后任何操作方法可以通过从UnitOfWork获取任何一组存储库,并且一旦完成所有更改,它就可以在unitOfWork上调用Commit,它将负责提交已在存储库中完成的所有修改。

这就是理论和总体思路。

现在更具体地说明ASP.NET MVC中的DI,DI容器的“管道”更常见的方式(有其他方式)是创建一个继承自IDependencyResolver的类,利用DI容器解析类型,并在Application_Start调用DependencyResolver.SetResolver这个类的实例。 这样,当要求ASP.NET MVC创建控制器(最终用户请求)时,它将通过此​​依赖性解析器来请求控制器的实例,并且此依赖性解析器将转向DI容器以创建实例通过照顾所有需要的注射来控制控制器。 您应该查看特定DI容器的网站/论坛,因为它们都显示了使用ASP.NET MVC进行检测的方法。

这只是一个非常高的概述,有很多棘手的细节,但这是一个重要的想法。

<强> EDIT2

刚刚在我的博客上发表了一篇文章(我的第一篇),解释了如何在ASP.NET MVC项目中正确使用Repository和UnitOfWork模式。

http://codefizzle.wordpress.com/2012/07/26/correct-use-of-repository-and-unit-of-work-patterns-in-asp-net-mvc/

答案 1 :(得分:1)

你在谈论ASP.NET MVC吗?

我和Ninject已经有一段时间了,我很高兴!查看此存储库中的示例应用程序,以了解如何在ASP.NET MVC 3中使用它:

https://github.com/ninject/ninject.web.mvc/tree/master/mvc3

要在回复中稍微扩展一下,这里是我设置Ninject绑定的代码片段

kernel.Bind(typeof(IUnitOfWork<>).To(typeof(UnitOfWork<>));

我的控制员:

public class MyController : Controller {
    private readonly IUnitOfWork<Student> uowStudent;
    public MyController(IUnitOfWork<Student> uowStudent) {
        this.uowStudent = uowStudent;
    }
}

然后你需要做的就是确保UnitOfWork类的构造函数中的任何参数也绑定在内核中。