Sunday, November 27, 2011

Dependency Injection and Ninject (Part 1)

Dependency Injection (DI) is a design pattern that is usually promoted for large software applications. However, it can be implemented in a view steps and the pattern immediately improves the maintainability and testability of an application. For that reason I have included Dependency Injection in my medium sized applications too. In this post and its follow-up I will demonstrate how to use Ninject, an open source dependency injector for .NET, to implement constructor injection.

What is dependency injection all about? Have a look at this code example:
public class SqlServerTermRepository
{
    public IList<Term> GetTerms() {
        List terms = new List();
        // ...Get terms from SQL Server database and add them to the list...
        return terms;
    }
}

public class TermService
{
    private SqlServerTermRepository _termRepository;

    public TermService()
    {
        _termRepository = new SqlServerTermRepository();
    }

    public IList<Term> GetTerms() {
        return _termRepository.GetTerms();
    }
}
The TermService class is part of the business logic layer (BLL) of a terminology management system that I am developing. It interacts with a data access layer (DAL) that contains repository classes to get data from an SQL Server database or to perform database updates. The service classes are instantiated in the controllers of the MVC application.

Since my data comes from an SQL Server database, the TermService creates an object 'SqlServerTermRepository'. Now lets assume we want to go open source and use MySQL for our databases instead. To make that change we have to modify the implementation of the TermService class. The TermService class is tightly coupled to the SqlServerTermRepository class. This should be avoided since it makes the application difficult to maintain.

In order to avoid tightly coupled classes, we can use interfaces to provide a level of abstraction. Let’s create an interface to represent a repository:
public interface ITermRepository
{
    public IList<Term> GetTerms();
}
Then, our SqlServerTermRepository class can implement this interface:
public class SqlServerTermRepository : ITermRepository
{
    public IList<Term> GetTerms() {
        List terms = new List();
        // ...Get terms from SQL Server database and add them to the list...
        return terms;
    }
}
And we can alter the TermService class:
public class TermService
{
    private ITermRepository _termRepository;

    public TermService(ITermRepository repository)
    {
        _termRepository = repository;
    }

    public IList<term> GetTerms() {
        return _termRepository.GetTerms();
    }
}
To let the service use SQL Server, we can pass an SqlServerTermRepository object via the service constructor. This is an example of Dependency Injection (specifically, constructor injection). If we want we can change the repository that the service uses to, for instance, a MySQLRepository (that of course must also implement ITermRepository) without having to modify the service code:
TermService service = new TermService(new MySQLRepository());
IList<Term> terms = service.GetTerms();
// ... Do something with the term list ...
In medium sized and large applications, objects like SqlServerTermRepository and MySQLRepository will themselves depend on other objects for their functionality. Rather than spending a lot of time creating and connecting all objects by hand (and doing a lot of refactoring when something changes), we can use a dependency injector like Ninject to do the work for us. In Part 2 of this post we will see how to integrate Ninject in our ASP.NET MVC application.

No comments:

Post a Comment