Dependency Injection to The Core (Part - II)

Say for example, our client changed their requirements and now wants us to read and write comma separated data (CSV) from a filesystem instead of a database. Suppose I’ve searched and downloaded a cool library that can work with CSV files. So, we have a CSV library configured and ready to talk with our CSV files in the data access layer.

If you are following me then you would say, now that we have a new data access layer, we also need a new repository. Right? Exactly! Since we want to do the exact CRUD operations but now against a CSV file, our method signatures will be the same as we have for the TodoRepository but the implementation will be different (because now we are using a new library instead of EF to talk to a CSV file). Let us not go into the implementation details, rather just create the repository and declare the methods. Let’s say the name of our new repository is TodoCSVRepository


public class TodoCSVRepository
{
    private readonly SomeCSVLibary _someCSVLibrary = new SomeCSVLibary();

    public IEnumerable<Todo> GetAll()
    {
        /* Use _someCSVLibrary library instance and get all the todo */
    }

    public void Add(Todo item) 
    {
         /* Use _someCSVLibrary library instance to add a new todo */
    }

    public Todo Find(int id)
    {
        /* Use _someCSVLibrary library to find a todo by id */
    }

    public Todo Remove(int id)
    {
        /* Use _someCSVLibrary library to remove a todo by id */
    }

    public void Update(int id, Todo item)
    {
        /* Use _someCSVLibrary library to update a todo */
    }
}

Suppose later our client changed the requirements again and now he/she provided us a new library which can talk to an in-memory database system. So, we require another repository (TodoInMemoryepository). But wait! Don’t you think every time when we are creating a new repository we are declaring the same sets of methods which do some CRUD operations against our preferred data storage? That’s not a big issue here but the issue is every time when our client is changing his requirements we are creating a new repository and instantiating that repository in the controller (modifying code, not making the code extensible). So, let’s stop us from modifying the controller code once and for all. We have to take care of this culprit line which is new-ing up a repository,

private readonly TodoRepository _todoRepository = new TodoRepository();

We can solve this problem of ours easily by creating an abstraction for our repositories. What I meant is we can extract an interface (abstraction) out of the repository and use that instead of the concreate type of a preferred repository. Since every repository has the exact sets of methods we can extract an interface out of them which basically looks like this,


public interface ITodoRepository
{
    void Add(Todo item);
    Todo Find(int id);
    IEnumerable<Todo> GetAll();
    Todo Remove(int id);
    void Update(int id, Todo item);
}

We can now make the repositories implement that simple interface (abstraction) like this,

TodoRepository.cs
public class TodoRepository : ITodoRepository { ... }
TodoCSVRepository.cs
public class TodoCSVRepository : ITodoRepository { ... }

With this simple abstraction of ours now we can modify the controller code and make it depend on an abstraction rather than a concreate type. Remember that culprit of ours? It should now look like this,

private readonly ITodoRepository _todoRepository = new TodoRepository();

Not done yet! We are still new-ing up a specific concreate repository. You can’t create an instance of a interface so still we are dependent on a specific repository. Why don’t we modify further? Let’s create an ITodoRepository field and instantiate it from the controller like this,


private readonly ITodoRepository _todoRepository;

public TodoController()
{
    _todoRepository = new TodoRepository();
}


As you can see now that our controller is dealing with the task of creating a concrete type. But we can delegate this task of creating a concreate type to someone else who will call this controller of ours. What I meant is if someone wants to use this controller of ours then he/she has to pass a new instance of the type of the concreate repository of their like as a parameter in the controller’s constructor.


private readonly ITodoRepository _todoRepository;

public TodoController(ITodoRepository todoRepository)
{
    _todoRepository = todoRepository;
}


In this way, we can pass the responsibility upward and make our controller safe from further code modification. This kind of design (passing the type of instance through constructor from somewhere else) is also known as the constructor injection pattern.

This also follows the fifth principle (Dependency Inversion Principle) of SOLID design principles which states that,

"High-level modules should not depend on low-level modules. Both should depend on abstractions."

Everything looks good but at this point your program won’t run as you expected because its expecting a instance of a repository type to be passed in the controller. So, we can do some pure man’s DI here (passing an instance of an concrete repository type from the default constructor) ,


private readonly ITodoRepository _todoRepository;

public TodoController() : this(new TodoRepository())
{

}

public TodoController(ITodoRepository todoRepository)
{
    _todoRepository = todoRepository;
}

Still we have to modify the controller code when we want to use a different repository. But we can go further and build a composition root where we can do this kind of type initializations. The composition root is a simple class which will get called when the application is first initialized. In that class, we can resolve the specific types for our abstractions.


public class CompositionRoot : IHttpControllerActivator
{
    public IHttpController Create(
        HttpRequestMessage request,
        HttpControllerDescriptor controllerDescriptor,
        Type controllerType)
    {
        if (controllerType == typeof(TodoController))
            return new TodoController(
                new TodoRepository());

        return null;
    }
}

As you can see here, we have configured our HTTPRequest in such a way that if someone requests the TodoController we will instantiate a new instance of TodoRepository and pass it to the controller's constructor. Likewise, we can change it to TodoCSVRepository or TodoInMemoryepository whenever we feel like. Now we have a single place to do all our dirty works of type initializations. In Web API projects we have to register this composition root in the Global.asax.cs file like this,


GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),new CompositionRoot());

One thing to remember here is, a composition root implementation varies from framework to framework. Here we are working with Web API so this won’t work for MVC (may work) and WPF applications. You have to find a way to implement those but don’t worry because the internet has a lot of code snippets that can ease up your task of creating a composition root for a specific framework. Tell you what, I learned how to make a composition root like this for Web API projects after reading a blog from Mark Seeman. Here is the link for it,

http://blog.ploeh.dk/2012/09/28/DependencyInjectionandLifetimeManagementwithASP.NETWebAPI/

That’s good since we have to deal with resolving tiny dependencies for this small project of ours. What if we have a large project where hundreds of dependencies are scattered around? In that cases, composition root won’t be a good idea. That is why in enterprise level, we use a well-known IoC (Inversion of Control) container to make our job easy. IoC containers can resolve dependencies recursively and they are also pretty much easy to configure. They allows us to work with dependency injection lifecycle easily. In next blog Ill talk about one of these containers.

To Be Continued