Special Offer: My C#/.NET Bootcamp Course is out now. Get 10% OFF using the code FRIENDS10.

Dependency Injection is one of the fundamental techniques in the modern world of object-oriented software development. For modern programming platforms like the .NET platform, there are many different approaches.

In this video, I am going to explain the fundamentals of dependency injection in C#. It is important to understand and think about the fundamentals before you just pick a random framework and start developing your application to find out later on down the road that you waste a lot of time setting up your application.

It’s not worth the effort. Do it right the first time. Learn the fundamentals.

Subscribe to my channel, if you do not want to miss a video:

Content

This video starts at the beginning thinking about code dependencies and why dependency injection is a thing in the first place. How does it work and which problem does it solve?

The video is not only talking about the stuff mentioned above, but there is also a big hands-on part in the second half of the video where I am writing code for an actual application. I refactor the existing code base to make use of a simple hand-written dependency injection mechanism. If you haven’t done something like this before, I highly suggest to try it out for yourself or watch the video.

0:30 Video overview
1:02 What is a code dependency?
3:56 Dependency Inversion Principle (DIP)
4:09 How does Dependency Injection work?
4:54 Implement a simple Dependency Injection solution

This video is part of a series about dependency injection and if you find it useful and don’t want to miss out on newer videos in the dependency injection playlist, subscribe to the YouTube channel and enable notifications. You’ll get notified when a new video has been released.

This video is part of the Dependency Injection playlist:

Transcript

The following part of this article contains the full transcript of the video for people who want to search the content or are not able to properly hear.

In this video, you’re going to learn about code dependencies and how Dependency Injection can improve your C# code. We are not just talking about it, we also write some code.
And now let’s learn about Dependency Injection in C#.

Introduction

Hi, I’m a Software Engineer with more than ten years experience on the .NET platform. My passion for learning and sharing knowledge as well as helping other developers improve are the reasons I started this channel.

Overview

Before we jump right into it, I want to make sure that you understand what you get from watching this video.

To make things simple, we first take a look at what a code dependency is.
Next, I want to make sure that you understand how Dependency Injection works and why applying it can improve your code.
In the last part of this video, we are going to implement a simple solution from scratch without using any third-party framework so that you can understand and implement this example step-by-step on your own.
And now let’s jump right into it.

Code Dependencies

Let’s take a look at the following example to make sure we understand what a code dependency is.

In this case, we have a user class with a Username property and a changeUsername method. We also have a notificationService property which holds a reference to an instance of the ConsoleNotification class.
The ConsoleNotification class is responsible for writing a changed username to the console.

In other words: We say the User class has a dependency on the ConsoleNotification class.

Code like this can be found in any business application mostly in a more complicated fashion. To keep things simple, we stick to this straightforward example in this video, but the concept also applies to more complex scenarios.

And now take a look at some code!

Code Example

We use this simple console application using the classes just talked about before. In the main method of the Program class we create a user called Tim and change its name to Robert using the changeUsername method.

The User class has a simple constructor accepting the username as its argument. Further, we create an instance of the ConsoleNotification class and assign it to the _notificationService field of the User class.
We also have a Username property and the ChangeUsername method which calls the notificationService.

The ConsoleNotification class has a single method called NotifyUsernameChanged accepting a user object as its argument. The current implementation of the method simply writes a message to the console.

If we start the program, of course the output in the console says “The username has been changed to Robert” as we expected.

Now let’s take a look at the code dependency in our code. In the User class we have the _notificationService field which holds a reference to an object of the type ConsoleNotification.
The User class depends on the ConsoleNotification class.

You might ask yourself; Why is having a code dependency a problem?

In general, having dependencies in our code is not a problem. Of course, we have different classes in our applications which all work with each other. Without communication between our classes, our code would have to fit in a single class. We all agree that this is not something we want.

But what is the actual problem?

The actual problem is that the User class as a domain type has a dependency on a small technical detail.
In a bigger system, the User class will be used in different spots in the entire application. Also, there will be completely different reasons for us to change either the User class or the notification system.
Therefore we want to make sure that the User class is not affected by changes to the notification system.

How do we fix our code?

The first step is to make sure we depend on an abstraction rather than an implementation. This is one of the basic rules of object oriented design and often defined as the Dependency Inversion Principle (DIP).

The Dependency Inversion Principle (DIP)

The Dependency Inversion Principle (DIP) states that high level modules should not depend on low level modules; both should depend on abstractions. Abstractions should not depend on details. Details should depend upon abstractions.”

To follow this principle, we create an abstraction for the ConsoleNotification class. In C#, we use interfaces to create abstractions. Therefore we implement an INotificationService interface. The only method in this interface is the NotifyUsernameChanged method accepting a user object as its argument.

Next, we change our ConsoleNotification class to implement our new NotificationService interface. Because the method signature matches the implementation of the ConsoleNotification class we do not have to make any further code changes.

In the User class, we can now change the type of the _notificationService property from ConsoleNotification to INotificationService. Great!

But wait, we still have a dependency on the ConsoleNotification class. The constructor of the User class still creates an instance of the ConsoleNotification class.

We can remove this dependency by using dependency injection.
First of all, we create a new constructor argument for the User class. This argument is of type INotificationService.

Next, we need to fix our code in the Program class. The User class now needs a second argument in its constructor. To fix the Program class, we create an instance of the ConsoleNotification class and pass it to the constructor of the User class.

We just made use of Dependency Injection. We inject an instance of the ConsoleNotification class as a NotificationService to the User class.

Let’s recap what we just did.

Summary

Let’s take a look at our classes in another class diagram.
Now both of our concrete classes depend on an abstraction. The User class and the ConsoleNotification class both depend on the INotificationService interface.

Let’s say we want to notify the system not only by writing the changed username to the console, but also call a Webservice to notify other applications. We can easily create a new implementation of the INotificationService interface and the only code file we need to change is our Program class. Everywhere in our application where we use the _notificationService the implementation defined in the Program class will be used.

This example is very simple and we only have a single consumer of the NotificationService. In bigger applications, there could be many consumers even hundred or thousand consumers.

The more classes you have in your program the more complex it becomes. You have to define the implementation for every abstraction in your application. This can become a huge mess. This is where Dependency Injection frameworks come into play.

Next video

In the next video, I will take it to the next level by explaining how to use a Dependency Injection framework and I will show you how we can integrate that framework into our example program.

Feel free to ask questions about this video in the comments, give me some feedback and if you like this video, please hit the like button below. See you in the next.

 

Claudio Bernasconi

I'm an enthusiastic Software Engineer with a passion for teaching .NET development on YouTube, writing articles about my journey on my blog, and making people smile.