Dependency Inversion Principle

Last principle stating that high-level modules should not be dependent low-level modules, and their dependencies should rely on abstraction by interfaces or abstract classes. In simple terms – we should minify dependencies from certain implementations. The best way to achieve it, is to rely on interfaces – then our code has small amount of dependencies, and as we know, interfaces are stable – it means, that if we do any changes to our interface, this change will be related with changes in interface implementation. Lets move on to wrong code, where high-module depends on low-level module:

public class Employee
{
    public string Name { get; set; }
}

public class EmployeeRepository
{
    public void Add(Employee employee)
    {
       //some code to add
    }
}

public class EmployeeService
{
    private EmployeeRepository _employeeRepository = new EmployeeRepository();

    public void Add(Employee employee)
    {
        _employeeRepository.Add(employee);
    }
} 

To start with, we have to define some basics, which are high-level modules and low-level modules. In example displayed above, EmployeeService is high-level module class, and low-level module is EmployeeRepository class. High-level module in this case is dependent on low-level module, because it uses implementation of EmployeeRepository class, which is obviously breaking spoken principle. To make this code correct, there is a need to „switch” this dependency, just like the name of principle states:

public class Employee
{
    public string Name { get; set; }
}

//created interface with one method implemented
public interface IEmployeeRepository
{
    void Add(Employee employee);
}

// EmployeeRepository class now inherits IEmployeeRepository interface
public class EmployeeRepository : IEmployeeRepository
{
    public void Add(Employee employee)
    {
        //some code to add
    }
}

//created constructor, which injects dependency
public class EmployeeService
{
    private IEmployeeRepository _employeeRepository;

    public EmployeeService(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
    }

    public void Add(Employee employee)
    {
        _employeeRepository.Add(employee);
    }
} 

Correct code above, our class EmployeeService does not depend on actual implementation of EmployeeRepository, but on its abstraction – in this case, IEmployeeRepository interface. Changes made in low-level module does not affect on high-level module, thanks to that we could „switch” our dependencies.