I am using Ninject in my MVC application and am trying to implement a Unit of Work repository pattern.

Specifically, I have defined a generic IUnitOfWork interface, I then want to use an instance of this interface in the constructor for some other (Business Logic classes). Here is the start of my Controller...

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
}

The Controller constructor works correctly, but I would like to find a clean way of constructing the various Business Logic classes so that they may reference the repositories within the UnitOfWork object.

The problem is that I can't instantiate a new Business Logic object from the interface, i.e. the following code fails:

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

As there is nothing to 'wire' the ICompanyService interface to a concrete implementation. What I would like it to do would be to use DI (Ninject) to create the instance of ICompanyService where the physical class's constructor would look like this:

public class CompanyService : ICompanyService {

    private readonly UnitOfWork db;

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

FINAL SOLUTION Further to the suggestions from Joshscorp and Dbaseman (thank you) I structured my code as follows:

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
}

The Ninject module is as follows:

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();
   }
}

The 'InRequestScope()' method on the IUnitOfWork binding ensures that the same instance of the UnitOfWork class is used in the constructors of the dependent classes CompanyService and EmployeeService.

This achieves exactly what I was looking for - a single instance of the IUnitOfWork object referenced by the dependent services classes.

有帮助吗?

解决方案

First of all, you cannot new up an Interface, only concrete classes.

new ICompanyService will never work.

Secondly, if you are usually MVC, I supposed you are using the DependencyResolver to resolve your objects, which is an anti-pattern according to some. Regardless of what you use to resolve the dependencies, you should always have a single point of entry to the application, i.e. per request in Global.asax etc... and a bootstrapper of some sort to load up the dependency object graphs.

In your example, what I would change is the constructor, taking in ICompanyService and IEmployeeService as well,

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
}

This is of cause assuming you registered the concrete implementations of ICompanyService and IEmployeeService with Ninject or any IoC container in the entry point of your app (not familiar with Ninject and don't recommend it)

You might wonder, how then did the IUnitOfWork instance get injected into the ICompanyService concrete object's constructor? The same way it got injected to the CompanyController's constructor!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top