Introducing Dependency Injection in .NET
Dependency Injection
2 Articles
In this article, let's learn about Dependency Injection
in .NET.
Table of Contents
- Introduction
- What is Dependency?
- Dependency Injection visualization
- Working with Dependency Injection
- Phases of Dependency Injection
- Advantages
- Summary
Introduction
.NET supports the dependency injection (DI)
software design pattern, which is a technique for achieving
Inversion of Control (IoC)
between classes and their dependencies. Dependency injection in .NET is a
built-in part of the framework.
What is Dependency?
A dependency
is an objec
that
another object
depends on. Examine the following ClassB class
with
that other classes depend on:
Code Sample - Dependency Injection Demo
A class
can create an instance
of the
ClassB class
to make use of it. In the following example, the
ClassB class
is a dependency of the ClassA class
:
Code Sample - Dependency Injection Demo
The class
creates and directly depends on the ClassB class
.
Hard-coded dependencies, such as in the previous example, are problematic and should be avoided for the following reasons:
- To replace
ClassB
with a different implementation, theClassA class
must be modified. -
If
ClassB
has dependencies, they must also be configured by theClassA class
. In a large project with multiple classes depending onClassB
, the configuration code becomes scattered across the app. -
This implementation is
difficult to unit test
. The app should use a mock or stubClassB
class, which isn't possible with this approach.
So let's try to get the instance of ClassB
from constructor
of
ClassA
.
Code Sample - Dependency Injection Demo
Here is the complete wire up in Program.cs
.
Code Sample - Before Dependency Injection
Dependency injection addresses these problems through:
-
The use of an
interface
orbase class
toabstract
the dependency implementation. -
Registration of the dependency in a service container. .NET provides a built-in service container,
IServiceProvider
. Services are typically registered at the app's start-up and appended to anIServiceCollection
. Once all services are added, you useBuildServiceProvider
to create the service container. - Injection of the service into the
constructor
of theclass
where it's used. The framework takes on the responsibility of creating an instance of the dependency and disposing of it when it's no longer needed.
Code Sample - After Dependency Injection
Dependency Injection visualization
DI enables decoupling and supports development of loosely-coupled code. DI supports implementation of
two related concepts, inversion of control
and the
dependency inversion principle
.
Inversion of Control
- - High-level modules should not depend on low-level modules.
Dependency Inversion Principle
- - A framework controls which code is executed next, not your code.
Working with Dependency Injection
DI Configuration consist of two main phases, Registration
phase and Resolving
Phase.
Steps
- Install
Microsoft.Extensions.Hosting
Nuget Package. Register services using
Code Sample - Registering Services
- Resolve services using
Host.Services.GetRequiredService<YourService>();
Phases of Dependency Injection
Registration Phase
Register types in container so it knows of their existence and when to construct them.
- Register types for later use.
- Indirection through service type and implementing type.
- Choose a lifetime.
Registering Types
When registering types you specify the lifetime, the requested service type and the implementing type. If these types are the same you provide it once.
Code Sample - Registering Types
Resolving Phase
Container is responsible for instantiating types and providing them when requested.
- Resolves and creates types directly.
- Provides dependencies of types you work with.
- Provides dependencies to dependencies of the types you work with.
- Manage the lifetimes of the types.
Resolving Types
When resolving a type, you request an instance of service type. The container will find the implementing type, instantiate it if needed, and return it to you.
If the implementing type has dependencies, they are provided to the implementing type as well.
Code Sample - Resolving Types
Advantages
- No longer calling constructors.
- Container calls the constructors.
- Not concerned with ordering registrations.
- Not concerned with dependencies of each type.
Summary
In this article, we learn't what is Dependency Injection
in .NET. We understood how classes are invoked in
traditional flow using new()
keyword and how dependency injection helped us to avoid the
new()
glue and makes it easy to manage dependencies. In next article lets talk about
lifetimes in dependency injection in .NET.