Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DI container for 2 layers

I'm trying to design WebApi application with using IoC like Ninject. I have the following layers(3 projects):

  • Domain(Repository) layer
  • Service
  • Web API application core

The Repository layer has interface IRepository<T> and a few implementations of it. And in the Service also exists interface IService<T> with a two different implementations.

Could you please advise me should I use DI container (Ninject) in WebApi project to bind IService<T> and ServiceConcrete<T> and DI container in the Service project to bind IRepository<T> and RepositoryConcrete<T>?

Or maybe should I use only one DI in WebAppi project?

like image 464
Roman Marusyk Avatar asked Jan 26 '16 23:01

Roman Marusyk


2 Answers

A practical way I have found to set up Ninject modules can be found below.

Overview

  1. Create an assembly called DependencyResolution
  2. Create the Ninject modules (that you will utilize in your WebAPI project)
  3. Have only this DependencyResolution and your Domain projects referenced in your WebAPI project
  4. Initalize/register your modules in NinjectWebCommon.cs

Details

  1. Should be easy as create a project, add Ninject as reference from NuGet for instance.
  2. Add new class file(s) to this project named after the modules you want to create like: ServiceModule.cs, RepositoryModule.cs, etc. Create your Ninject module(s). For detailed instructions on this you can refer my answer on this.
  3. In your WebAPI project, you add reference to this just created DependencyResolution project and your Domain project.
  4. Initializing/registering your just created module(s) in the WebAPI project's NinjectWebCommon.cs as:

    private static void RegisterServices(IKernel kernel)
    {
        var modules = new List<INinjectModule>
        {
            new ServiceModule(),
            new RepositoryModule()
        };
    
        kernel.Load(modules);
    }  
    

I will also try to address another concern that is loosely related to your question. I think your current layering setup would need a bit to be changed.

The basic and probably my biggest problem with your layers are that you mix up and therefore tightly couple the Domain and Repository which is clearly an infrastructural concern.

I would suggest to re-architect your layers as:

  • Domain
  • Services
  • Infrastructure (Repository implementations could go here for instance)
  • Dependency Resolution
  • WebAPI

Do not forget that your Domain layer should not have any idea about infrastructural details like Repository, else you are going to tightly couple your domain with unneeded implementation details.

EDIT: From the comments I see that you have some concerns about where to place and how to name things which is obviously one of the hardest things in programming.

So my thoughts on clearing this confusion up are:

Layer: is a logical separation or collection point of classes, methods, etc. that those belong together.

Each layer can consists of multiple projects or assemblies. So if you want to categorize your projects into layers, you could create directories in your solution named about your layers and place the individual projects inside these directories. It's really just a matter of taste in the mouth, take it just as a tip.

Example structure

  1. Solution root
  2. Core directory
    • Domain assembly: the root of you domain where you have your business or domain entities AND the all the interfaces that your domain is using.
    • Domain services assembly (just could be in Domain assembly as well)
  3. Services directory
    • Application services assembly: for example an example this assembly houses services or facades that spans operations accross multiple domain entities or aggregates, etc.)
  4. Infrastructure directory
    • Repository assembly: this is where you have the implementations of your EF repositories
    • Custom logging/email/whatever else assemblies or implementations that doesn't belong to the domain.
    • DependencyResolution assembly: this is the place of your NInject modules and all IOC container related wirings.
  5. UI directory
    • WebAPI assembly
    • Asp.Net MVC assembly

Summary

The Dependency Resolution project has references to any needed assemblies (Domain for interfaces, Services/Infrastructure for their implementations) and wire them altogether for later use.

The WebAPI project would only need to have reference added Domain and Dependency Resolution so then you could just ask for your interfaces in your WebAPI methods/functions public constructor and Ninject will do the dirty job for you behind the scenes.

Please don't forget that this is just an easy quick 'n dirty architecture suggestion of mine, without knowing your exact requirements and use cases.

like image 102
kayess Avatar answered Sep 21 '22 18:09

kayess


If I understand your question, you're having troubles configuring your Repository layer because your config code is in your application layer, which probably only references your service layer (which in turn references your repository layer). What I've done in order to get around this is first create your configurations in modules (these can live on any layer, but you must reference Ninject)

For your repo layer:

public class RepoNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMyRepo>().To<MyRepo>();
    }
}

create a similar Module in your service layer:

public class ServiceNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMyService>().To<MyServce>();
    }
}

Then, in your application layer, you can load the modules dynamically (this is what NinjectWebCommon.cs looks like):

private static void RegisterServices(IKernel kernel)
{
    kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
}

More info on modules: https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel

like image 22
solidau Avatar answered Sep 21 '22 18:09

solidau