1
votes

I'm working on a project that has multiple layers of architecture. These layers are in their own class library projects, but all in the same solution. At the lower layers, I've got the repository pattern going, with my models, repositories and dbcontext. On top of my repositories sits a service layer, which contains all of my business logic. Right now, my code for instantiating and using these various components looks like this, in my unit tests:

using (var context = m_kernel.Get<IPortalContext>())
{
    var accountRepository = m_kernel.Get<IAccountRepository>(new ConstructorArgument("context", context));
    var eventRepository = m_kernel.Get<IEventRepository>(new ConstructorArgument("context", context));

    var accounts = m_kernel.Get<IAccountService>(new ConstructorArgument("repository", accountRepository));
    var events = m_kernel.Get<IEventService>(new ConstructorArgument("repository", eventRepository));

    var account = accounts.GetByUsername("[email protected]");
}

You can see I create a context, then I create my repositories and give them the existing context, finally I create my services and give them the repository. Then, I am free to use the services.

That code is very verbose, though. I can make it cleaner by creating the repository instances inside of the services, instead of outside.

My confusion comes while trying to do this, though. I use Ninject for my DI, and I want to create an instance of the class bound to the IAccountRepository interface inside of my IAccountService constructor. On top of that, it needs to know to use the provided IPortalContext as well.

Do I have to add Ninject as dependency to my service layer project and create a new Kernel in there and use Kernel.Get() inside for the IAccountService constructor? Or is there a way to tell Ninject to do this all from my unit test, for example?

1
Creating the repositories inside of the services is not dependency injection. If you do it that way, you'll be using Ninject as a Service Locator, which is arguably an anti-pattern. The architecture you have here, with dependencies injected into the classes that need them, is the way IOC containers like Ninject are meant to be used. Ideally IOC containers should only be used in one place in your application, not spread out across classes and projects. For more info, check out the book "Dependency Injection in .Net" by stackoverflow user Mark Seemann, it really helped me out.Charles Josephs

1 Answers

2
votes

I want to create an instance of the class bound to the IAccountRepository interface inside of my IAccountService constructor

Then why are you using NInject? That dependency should be injected (hence the name), not created within the service.

It may seem "cleaner" to do this inside the service, but you lose all of the benefit of loosely coupling your layers.

If you find you're repeating these 6 lines of code (which is not "verbose" IMHO) then you could refactor that into a separate function (in your unit tests and your app layer) and call it whenever you need to.