Dependency Inversion Principle (DIP) in C#

In my previous articles I wrote about Solid Principles in C#.

In this article, I am going to show you when and how to use the Dependency Inversion Principle (DIP) in C# with an example project. You can find the repository on GitHub.

The master branch shows the initial code used in the example.  There are separate tags and branches for each of the all solid principles that you can review or download as well. Here are links you can use to jump to these tagged versions in your browser:

What is the Dependency Inversion Principle (DIP) in C#?

The Dependency Inversion Principle (DIP) is the last, in alphabetical order, of the SOLID design principles. We can always reuse the definition from Wikipedia.

High-level modules should not import anything from low-level modules. Both should depend on abstractions.

Abstractions should not depend on details. Details should depend on abstractions.

Let’s try to summarize these two definitions:

  • Instead of high-level modules relying directly on low-level modules, both should communicate through abstract interfaces. This promotes flexibility and allows for easier substitution of components.
  • Abstractions should not be tightly coupled to specific implementations; instead, the concrete details should adhere to the abstractions. This allows you to change or extend implementations without affecting the overall structure of your code.

Abstractions describe what:

  • Send a message;
  • Store a record;

Details specify how to do:

  • Send a push notification to a device;
  • Deserialize an object and store in a database;

In this example we expose implementation details and making the interface much less reusable. The interface should not know the details of the database, in this case mysql.

public interface IOrderDataAccess
{
    MySqlDataReader GetOrders(MySqlParameterCollection params);
}

This example hide the details above and make the interface reusable.

public interface IOrderDataAccess
{
    List<Order> GetOrders(Dictionary<string, string> params);
}

Continue reading