依赖类的构造函数注入

时间:2012-09-03 14:22:44

标签: c# .net dependency-injection ninject ninject.web.mvc

我在我的MVC应用程序中使用Ninject,并且正在尝试实现Unit of Work存储库模式。

具体来说,我已经定义了一个通用的IUnitOfWork接口,然后我想在构造函数中为其他一些(Business Logic类)使用这个接口的实例。这是我的控制器的开始......

public class CompanyController : Controller
{
    private readonly IUnitOfWork UnitOfWork;
    private readonly ICompanyService CompanyDb;
    private readonly IEmployeeService EmployeeDb;

    public CompanyController(IUnitOfWork unitOfWork)
        : base()
    {
        this.UnitOfWork = unitOfWork;
        // This following construction is the problem...
        this.CompanyDb = new ICompanyService(this.UnitOfWork);
        this.EmpoloyeeDb = new IEmployeeService(this.UnitOfWork);
    }

    // Rest of Controller implementation
}

Controller构造函数正常工作,但我想找到一种构建各种Business Logic类的简洁方法,以便它们可以引用UnitOfWork对象中的存储库。

问题是我无法从界面实例化新的Business Logic对象,即以下代码失败:

this.CompanyDb = new ICompanyService(this.UnitOfWork);

因为没有什么可以将ICompanyService接口“连接”到具体实现。我希望它做的是使用DI(Ninject)来创建ICompanyService的实例,其中物理类的构造函数将如下所示:

public class CompanyService : ICompanyService {

    private readonly UnitOfWork db;

    public CompanyService(IUnitOfWork unitOfWork) {
        this.db = unitOfWork as UnitOfWork;
    }
}

最终解决方案 继Joshscorp和Dbaseman的建议(谢谢)后,我的代码构造如下:

public class CompanyService : ICompanyService {

    private readonly UnitOfWork db;

    public CompanyService(IUnitOfWork unitOfWork) {
        this.db = unitOfWork as UnitOfWork;
    }

    // Rest of implementation
}


public class CodeFirstController : Controller {

    private readonly IUnitOfWork UnitOfWork;
    private readonly ICompanyService CompanyDb;
    private readonly IEmployeeService EmployeeDb;


    public CodeFirstController(
        IUnitOfWork unitOfWork,
        ICompanyService companyDb,
        IEmployeeService employeeDb
    ) : base() {
        this.UnitOfWork = unitOfWork;
        this.CompanyDb = companyDb;
        this.EmployeeDb = employeeDb;
    }

    // Rest of implementation
}

Ninject模块如下:

public class CodeFirstModule : NinjectModule {
    public override void Load() {
        string connectionString = ConfigurationManager
            .ConnectionStrings["CompanyConnection"]
            .ConnectionString;


        Bind<CodeFirst.DAL.IUnitOfWork>()
           .To<CodeFirst.DAL.EntityFramework.UnitOfWork>()
           .InRequestScope()
           .WithConstructorArgument("connectionString", connectionString);

        Bind<CodeFirst.DAL.ICompanyService>()
           .To<CodeFirst.DAL.EntityFramework.CompanyService>()
           .InRequestScope();

        Bind<CodeFirst.DAL.IEmployeeService>()
           .To<CodeFirst.DAL.EntityFramework.EmployeeService>()
           .InRequestScope();
   }
}

IUnitOfWork绑定上的'InRequestScope()'方法确保在依赖类CompanyService和EmployeeService的构造函数中使用UnitOfWork类的相同实例。

这实现了我正在寻找的东西 - 依赖服务类引用的IUnitOfWork对象的单个实例。

1 个答案:

答案 0 :(得分:2)

首先,你不能新建一个接口,只能打造具体的类。

new ICompanyService永远不会奏效。

其次,如果你通常是MVC,我认为你正在使用DependencyResolver来解析你的对象,这是一种反模式。无论您使用什么来解决依赖关系,您都应该始终只有一个应用程序入口点,即Global.asax等中的每个请求......以及某种类型的引导程序来加载依赖项对象图。

在您的示例中,我将更改的是构造函数,同时接收ICompanyServiceIEmployeeService

public class CompanyController : Controller
{
    private readonly IUnitOfWork unitOfWork;
    private readonly ICompanyService companyDb;
    private readonly IEmployeeService rmployeeDb;

    public CompanyController(IUnitOfWork unitOfWork,
        ICompanyService companyDb, 
        IEmployeeService  employeeDb)
    {
        this.unitOfWork = unitOfWork;
        this.companyDb = companyDb;
        this.empoloyeeDb = employeeDb;
   }

    // Rest of Controller implementation
}

这是假设您在应用程序的入口点注册了ICompanyServiceIEmployeeService与Ninject或任何IoC容器的具体实现(不熟悉Ninject并且不推荐它)

您可能想知道,IUnitOfWork实例如何被注入到ICompanyService具体对象的构造函数中?它被注入CompanyController的构造函数的方式相同!