【问题标题】:Constructor Injection for Dependent Classes依赖类的构造函数注入
【发布时间】:2012-09-03 14:22:43
【问题描述】:

我在我的 MVC 应用程序中使用 Ninject 并尝试实现工作单元存储库模式。

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

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 构造函数工作正常,但我想找到一种简洁的方法来构造各种业务逻辑类,以便它们可以引用 UnitOfWork 对象中的存储库。

问题是我无法从接口实例化新的业务逻辑对象,即以下代码失败:

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 对象的单个实例。

【问题讨论】:

  • 我不清楚你想知道什么。你说你喜欢找到一种简洁的方式来构建各种类,以便它们可以引用存储库?但是你目前的问题是什么?请使用更多信息(可能是更多代码)更新您的问题。

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


【解决方案1】:

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

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
}

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

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

【讨论】:

  • 感谢 Joshscorp。我希望在两个/(所有)依赖类中使用相同的 IUnitOfWork 实例,以便数据上下文在所有业务逻辑类中同步/通用。如果我按照您的指示使用构造函数,我最终不会得到三个单独的 IUnitOfWork 对象,每个构造类一个吗?
  • @Neilski 与 Ninject 您可以在特定范围内绑定,例如 Bind&lt;IUnitOfWork&gt;().To&lt;UnitOfWork&gt;().InRequestScope()InSingletonScope()
  • 是的,您可以像 dbaseman 所说的那样指定要注入的相同实例
猜你喜欢
  • 2011-02-02
  • 2011-09-02
  • 2013-01-30
  • 2018-06-17
  • 2019-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多