Photo by Luke Peters on Unsplash

Get started with Dependency Injection

In object oriented software development, we work with a bunch of objects and classes. All should be as independent as possible and changing code should be easy. When it comes to changes you’ll see how good a program is structured. Does one change impact the whole building process or leads to a total disfunction of the program? What if you want to replace a class with a different class?

Let’s say you have a class which stores data in a CSV file, but now you want to store all the data in a database. Do you know which dependencies you have? Which functions have to be rewritten? To have an easier life in software development I want to show you the concept of Dependency Injection.

What is it?

Basically, Dependency Injection is used to reduce the number of dependencies between different classes. Imagine you have a book with an index where you can see on which page you find all the informations to a specific topic. In the software development environment you create such an index for your program to say which interface should be replaced with which implementation. The client doesn’t have to decide which class should be used. It’s the injector who decides it.

Another principle which is often times used together with Dependency Injection is “Inversion of Control (IoC)”. The main point here is that you just decide WHAT you want to do NOT HOW. And some point in the program you want to store some data.

For the implementation it doesn’t matter how the data is stored (in a SQL or NoSQL database, in a file etc.). The implementation just calls a method to store the data. You have an IoC container that works as an index. Here you can find which dependencies are used for which types. There could be an interface called “IDataStorage”. Within the IoC container there’s a registration for the concrete implementation class, for instance “SQLDataStorage” or “FileDataStorage”.

Why use it?

Maybe the following questions come into your mind: “But why should I use it? What is my benefit?”. Maybe you recently have started to work on a new project. The software is quite small but becomes bigger over time. And don’t forget that the majority of work in software development is to maintain and to add new functionalities.

As mentioned above, maybe you’ll have a requirement that’ll change over time (like storing data in a database instead of storing it in a local file). And even worse, what if you only have a limited amount of time to migrate all the storing functionality? Changing code with lots of dependencies will take some time. You have to review all classes which use the code, modify functions, and don’t forget about automated tests! The bigger the software is the greater the problem becomes.

Practice

I think the basic concept and the reason why we use it should be clear. Let’s head to some code. The application is written in C# but you can also use other languages to apply this pattern. Dependency Injection also works without any framework, but to have an easier start I’d suggest to use one. Especially, if you want to use an IoC container. In this case I use “Autofac”.

The following code is the default ASP.NET Core Web-API code with the weather forecast service. You just have to choose the Web-API template to get started.

Visual Studio project template selection screen when creating a new application.
Selecting the API template gives you the boilerplate code to follow my example

Implementing the basics

I won’t get into the details of the template itself, but I’ll show you the changes I made. First, I created an interface to define my “StoreCurrentWeatherValues” method. It accepts an IEnumerable of a “WeatherForecast” object and returns a boolean value to show whether storing the values was successful or not.

The interface is the base for our caller. It says which methods are available. It can already be used to develop the caller (in this case I just added some code to the default controller).

But an interface doesn’t contain any implementation. So I built a class based on the interface to store the values in a CSV file.

It joins all the data of a “WeatherForecast” object to a string matching the CSV format and creates a file on the disk. You might wonder how the controller now can use the freshly built CsvWeatherValuesService.

Adding DI and IoC Container

That’s the part where the Dependency Injection and the IoC container take place. To use Autofac for it, we need two NuGet packages:

  • Autofac
  • Autofac.Extensions.DependencyInjection

Autofac itself is an IoC container to manage the dependencies between all classes whereas Autofac.Extensions.DependencyInjection implements the ServiceProvider and other interfaces of Microsoft.Extensions.DependencyInjection.Abstractions. With this Extension you can use the AutofacServiceProviderFactory to easily register all your dependencies.

Let’s have a look on the code. The ServiceProviderFactory is registered in the Program.cs file.

The registration of AutofacServiceProviderFactory allows us to use the method “ConfigureContainer” in the Startup.cs class. There we can register the module which contains all Autofac registrations.

Currently with only one Interface and one implementation our Autofac Module is really straightforward and registers only one type.

But if we add some other services or we want to change from a file based storage to a database we just have to add the new code and change the registration.

Switching implementation with Dependency Injection

Let’s take the example of changing the storage type. The connection and transactions with the database are done with EF Core. To create the SqliteWeatherValuesService I only have to ensure that I also implement the interface IWeatherValuesService. So the methods that have to be implemented are clear — it’s just “StoreCurrentWeatherValues”.

After adding the implementation the registration in the AutofacModule needs to be adjusted. Instead of registering the CsvWeatherValuesService we now use the SqliteWeatherValuesService.

Now all the values will be stored in a SQLite database without touching the controller. We only added the implementation of the database work and changed the registration. Not only is it an advantage when modifying the code, but also it fulfills the Open-Closed-Principle — one of the five SOLID principles we should respect during the development.

Summary

In this article I showed you what “Dependency Injection” is, why you should use it, how it works together with an IoC container and I gave you an implementation example using the framework “Autofac”. I hope you find it useful and you’ll use it in future project to improve readability and maintainability of your software. If you want to check out the whole example, just have a look on my GitHub repository.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nicolas W

Nicolas W

Passionate software engineer. Primarily developing API services and backend applications.