Design Patterns - Dependency Injection

What is dependency injection and why you should use it.

The Dependency Injection pattern suggests that a class should not directly instanciate it’s dependencies but, instead, should provide a way for the dependencies to be “injected” - usually as constructor parameters.

Without dependency injection

public class UserService
{  
    private readonly UserRepository _userRepository;

    public UserService(string connectionString, CachingOptions cachingOptions)
    {
        _userRepository = new UserRepository(connectionString, cachingOptions);
    }
}

Refactored to use dependency injection

public class UserService
{  
    private readonly UserRepository _userRepository;

    public UserService(UserRepository userRepository)
    {
        _userRepository = userRepository;
    }
}

Notice how after the refactoring, UserService class does need to know how create a UserRepository but only how to use it. This reduces coupling and is a step towards Single Responsibility design pattern.

There is another refactoring that we can make that although is not strictly part of Dependency Injection (but more part of Dependency Inversion) it allows for much greater flexibility and decoupling.

Refactored to use Dependency Inversion


public interface IUserRepository 
{
    ...
}

public class UserService
{  
    private readonly IUserRepository _userRepository;

    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }
}

After this second refactoring, the UserService does not depend on the concrete implementation of the UserRepository but on the interface IUserRepository and this makes it much more easier to mock the UserRepository for unit testing.


public class TestUserRepository: IUserRepository
{
    public User[] GetUsers 
    {
        return new [] {new User (...), new User(...)};
    }
}

public class UserServiceTests
{
    public void Test()
    {
        var service = new UserService(new TestUserRepository)

        Assert(2, servive.GetAllUsers().Length);
    }
}
Thomas Sarmis
Software Engineer

I am a software engineer / system architect with experience in gaming (gambling)