Dependency Injection: What it is and How to Use it


Introduction

In software engineering, dependency injection is a technique that enables a class or module to receive its dependencies from an external source rather than creating them itself. This approach decouples the code from external dependencies, making it easier to test and maintain.

What is Dependency Injection?

Dependency Injection (DI) is a design pattern that helps you decouple the code by passing dependencies to a class or module. It is a technique where one object supplies the dependencies of another object. It is a way to achieve loose coupling between objects and makes it easier to test, maintain and extend your code.

How to Use Dependency Injection with Examples

Let's take a look at an example of how to use dependency injection in C# code. Suppose we have a class called UserService which is responsible for creating and managing user accounts. The UserService class requires a UserRepository object to interact with the database.

public class UserService
{
    private readonly IUserRepository _userRepository;

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

    public void CreateUser(User user)
    {
        _userRepository.Create(user);
    }

    public void UpdateUser(User user)
    {
        _userRepository.Update(user);
    }

    public void DeleteUser(int id)
    {
        _userRepository.Delete(id);
    }

    public User GetUser(int id)
    {
        return _userRepository.Get(id);
    }
}

Here, we use dependency injection to pass the IUserRepository object to the UserService constructor. This way, we can easily replace the implementation of the IUserRepository interface with a different implementation, such as a mock repository for testing.

public interface IUserRepository
{
    void Create(User user);
    void Update(User user);
    void Delete(int id);
    User Get(int id);
}

public class SqlUserRepository : IUserRepository
{
    public void Create(User user)
    {
        // Code to create user in SQL database
    }

    public void Update(User user)
    {
        // Code to update user in SQL database
    }

    public void Delete(int id)
    {
        // Code to delete user from SQL database
    }

    public User Get(int id)
    {
        // Code to get user from SQL database
    }
}

public class InMemoryUserRepository : IUserRepository
{
    private readonly List<User> _users = new List<User>();

    public void Create(User user)
    {
        _users.Add(user);
    }

    public void Update(User user)
    {
        var index = _users.FindIndex(u => u.Id == user.Id);
        _users[index] = user;
    }

    public void Delete(int id)
    {
        _users.RemoveAll(u => u.Id == id);
    }

    public User Get(int id)
    {
        return _users.FirstOrDefault(u => u.Id == id);
    }
}

Conclusion

Dependency Injection is a powerful technique that helps you decouple the code and achieve loose coupling between objects. It makes it easier to test, maintain, and extend your code. By using DI, you can easily replace dependencies with mock objects for testing purposes, and you can also swap out implementations of dependencies without changing the code that uses them.


Comments