0

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

4

1 回答 1

2

首先,您不能新建接口,只能新建具体类。

new ICompanyService永远不会工作。

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

在您的示例中,我要更改的是构造函数,ICompanyService以及IEmployeeService

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
}

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

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

于 2012-09-03T16:13:55.880 回答