Originally posted on https://samueleresca.net
Dependency injection is a set of software design principles and patterns that enables us to develop loosely coupled code, it is also one of the most misunderstood concepts in the object oriented programming. The Dependency injection pattern is strictly related to SOLID principles, for more information: SOLID principles using Typescript The main purpose of the DI is the maintainability through the loose coupling technique, here is some benefits gained form the loose coupling:
Late binding
Services can be swapped with other services, late binding refers to the ability to replace parts of an application without recompiling code. For example, the following case allows developers to refers the interface IDataProvider and switch between an relational database and a NoSQL database without change the code:
Extensibility and Maintainability
Code can be extended and reused, and the responsibility of each class becomes clearly defined. Finally, adding a new features  is more easy because the structure of code allows developers to understand where apply changes.
Testing
DI is an important part of supporting unit testing. Unit tests provide a rapid feedback on the state of an application, but it is only possible to write unit test when the unit can be properly isolated from it's dependencies. By using DI, developers have the capability to inject dependencies and mocks inside the application code to test an specific part of application without affecting others.
Here is a simple example of mocking for unit testing:
public class DropDownDataControllerTest
{
[TestMethod]
public void GetDatesShouldReturnDatesFromRepository()
{
//Arrange
var mockRepository = new Mock<IDropDownDataRepository>();
var dateEntities = new[] { new DateEntity { Date = new DateTime(1990, 1, 1) }, new DateEntity { Date = new DateTime(1990, 1, 1) } };
mockRepository
.Setup(x => x.GetDates())
.Returns(dateEntities);
DropDownDataController controller = new DropDownDataController(mockRepository.Object);
//Act
var response = controller.GetDates();
//Assert
Assert.AreEqual(dateEntities, response);
}
}
Dependency Injection containers
DI container is a software library that can automate many of the tasks involved in composing object and managing their lifetimes. The DI containers usually expose a Resolve method: it resolves instances of arbitrary types. The DI containers know how to compose the requested type by using a sort of configuration or registration point where you map the abstractions(or interfaces) to concrete types. Finally, DI containers inherently compose object graphs by combining their own configuration with the information  from classes constructors*.*
DI containers configuration
There are 3 ways to configure DI containers:
- Static file as configuration: JSON or XML store informations about the DI mapping. The advantage is that it supports replacement without recompiling, the disadvantage is the no compile-time check;
- Code as configuration: the DI mapping is specified inside the code. The advantage is the compile-time check, the disadvantage is that it not support the replacement without compiling code;
- Auto-registration: a set of rules (or naming convention) locates suitable components and build the mappings. The advantage is that supports replacement without recompilation and enforce conventions to make a code base more consistent. The disadvantage is that there is not compile-time check;
DI container patterns
There are some patterns that describe the right way to use DI containers:
- Composition root: the mapping between concrete classes and interface must be composed as close as possible to the application entry point. The Composition root should be an unique location in the application;
- **Register, Resolve, Release: Â **The Register, Resolve and Release pattern describes how to use a DI container. The Register Resolve Release pattern states that a DI Container's methods must be invoked in this strict sequence. The
Registermethod register components with container. TheResolvemethod resolves the concrete class basing on an interface. Finally,ÂReleasemethod destroys the instances when they are no longer needed.
Dependency injection patterns
The Dependency injection patterns describe different ways to implement the Dependency injection inside our application. The most important is the Constructor injection pattern.
Constructor injection
The class that uses the dependency exposes a public
