This is more of a beginners guide in understanding Dependency Injection (DI) with mainly C# and using very basics of Asp.net Web API project. In summary it is the difference between a class creating its own dependencies vs those dependencies are injected into the class from an external source. Interfaces are also a core concept and below blog tries to explain the combined power of DI and interfaces.
Summary
DI is one the most commonly used design principles in software development. Overall the idea is to have loose coupling between dependencies and help in cleaner and better manageable code. I will be using a generic WebAPI project and controller/model structure to explain this instead of just saying Class A/B etc. I am not going detailed into code and want to stay bit generic.
Tight Coupling
Tight coupling is one of the problems in software development. Let’s say you have a class called HomeController which needs another class Logger to perform logging activity. Other similar requirements is like ShoppingService which needs a PaymentService to process payments. HomeController nor ShoppingService can be used without having their dependencies with it. This results in tight coupling.

Though it looks harmless, it creates roadblocks and looses flexibility. Below are few issues,
- Imagine Logger class is doing logs on screen like Console.WriteLine. HomeController can now only use this form of logging. It is tied to this form of logging via the Logger implementation.
- Another issue is Testing, if we need to test HomeController class, we need a implementation of Logger class. It gets difficult if Logger is depending on another class. In such cases to test HomeController we need to generate a Logger then any other dependencies Logger needs.
- Say the payment service and shopping service is developed by different teams, with the tight coupling they both are tied to each other. Any major changes to payment service will affect shopping service.
Interfaces
Answer to tight coupling is interfaces. Below is a huge jump from the tightly coupled HomeController. Here we say that HomeController needs a ILogger.
ILogger is an interface with one method Log(). This opens up a lot of possibilities. HomeController is no longer tied to Logger but to an interface ILogger.

Thus any class which implements ILogger can be used by HomeController. With this one change, suddenly HomeController can use a SccreenLogger or FileLogger or DBLogger or any other future classes which implements ILogger interface.

Dependency Injection
At first HomeController depended on Logger and using interfaces it now depends on ILogger. Now, still we have some coupling HomeController needs a ILogger implementation. This is where DI comes to rescue. A Dependency Injection (DI) container is a framework that manages the instantiation and injection of dependencies into classes. What it means for HomeController is that, the DI container will create the ILogger which it needs. HomeController doesn’t need to worry about life of the ILogger. In code it would something like below.
In an ASP.net Project in Program.cs we can use the builtin DI controller to tell the program that if someone needs ILogger use for example – FileLogger.
builder.Services.AddSingleton<ILogger, FileLogger>();
In HomeController.cs which needs ILogger will be handed a FileLogger from above by the builtin DI container. If it needs a SQLLogger we can modify in Programc.cs to make it a SQLLogger without any change to HomeController.
public HomeController(ILogger Logger)

This can also be put behind a factory or a configuration which determines what type of Logger is getting used. While during development or in specific environments like DEV, logging will be done to screen (ScreenLogger) and while in Production logging happens to a SQL table (DBLogger).
Thus HomeController is no longer tied to one implementation of logging. We can test functionalities of the HomeController my just mocking up an ILogger it doesn’t have to be concrete Logger class itself. Different teams can work parallelly as long as they respect the contract of ILogger. Logger team can make the text which appearing on screen logger bigger, different color and none of these really affects HomeController.
Few common mistakes/best practices
- Over using DI is a problem. It can get complicated easily
- Proper Scope Management needs to be there. Understanding what a class is dependent on and is there additional requirement for the dependent class etc. and this is something to be taken special care about. Singleton vs Transient vs Scoped all comes into play here which we have not discussed here.
Related topics
Above is more of a summary and DI has bit more core concepts like,
- Different ways DI container can provide the dependencies like as constructor injection
- Patterns like Singleton, Scoped, and Transient which defines the life of the object created
Leave a Reply