20
DecWhat is Dependency Injection in C# With Example (Guide)
23 Sep 2024
Intermediate
896K Views
16 min read
Dependency Injection In C#
Dependency Injection is a key concept in C#'s object-oriented programming. Unlike hard-coding them inside, it allows you to inject dependencies into a class. This allows for a more flexible and modular architecture, making the system easier to understand, test, and maintain.
In this design pattern tutorial, we will discuss Dependency Injection in C#, which comprises what Dependency Injection in C# is. And when should we utilize Dependency Injection? We'll also look into Dependency Injection in C#, with examples. So, let us begin by examining "What is Dependency Injection?".
What is Dependency Injection in C#?
- Dependency Injection (DI) is a C# design pattern that implements Inversion of Control (IoC) by allowing an object's dependencies to be injected at runtime rather than hard-coded.
- This enhances both modularity and testability. Consider an automobile production system in which the engine is injected into the assembly line rather than the car producing the engine.
- This allows multiple engine types to be utilized alternately without changing the car's class.
When to use Dependency Injection?
- Dependency Injection improves the flexibility and testability of your code.
- It is especially handy when your classes have shifting dependencies or when you wish to easily swap out components of your system, such as using various data sources or fake objects for testing without affecting your application's main functionality.
How do you Implement Dependency Injection in C#?
To set up Dependency Injection in C#, first define interfaces for dependencies and provide concrete implementations. Then, injection is used to pass these dependencies into classes. Finally, a DI container (such as Microsoft Extensions.DependencyInjection) should be set up to handle and resolve these dependencies at runtime.
Dependency Injection in C# allows for implementation in the following ways:
- Constructor Injection
- Setter Injection
- Method Injection
1. Constructor Injection
- Constructor injection is a type of dependency injection in which dependencies are passed to a class via its constructor.
- This method ensures that all necessary dependencies are present and initialized when an object is created, supporting immutability and making the class easier to test and manage.
The following are the steps for developing Dependency Injection using constructor injection in C#:
- Define Interfaces: Create interfaces for the dependencies that your class needs.
- Implement Interfaces: Provide concrete representations of these interfaces.
- Use Constructor Injection: Inject dependencies into the class constructor.
- Set up DI Container: Configure a DI container, such as Microsoft.Extensions.Dependency Injection manages and resolves dependencies.
- Resolve dependencies: Retrieve instances from the container that have dependencies injected.
Example
let's see the example of constructor Injection with C# Compiler
public interface IService {
void Serve();
}
public class Service1 : IService {
public void Serve() {
Console.WriteLine("Service1 Called");
}
}
public class Service2 : IService {
public void Serve() {
Console.WriteLine("Service2 Called");
}
}
public class Client {
private IService _service;
public Client(IService service) {
this._service = service;
}
public ServeMethod() {
this._service.Serve();
}
}
Program Class
{
static void Main(string[] args)
{
//creating object
Service1 s1 = new Service1();
//passing dependency
Client c1 = new Client(s1);
//TO DO:
c1.ServeMethod();
Service2 s2 = new Service2();
//passing dependency
c1 = new Client(s2);
//TO DO:
c1.ServeMethod();
}
}
Explanation
In the constructor injection example, each new Client instance is created with a unique IService implementation, which generates output based on the injected service. In the property injection example, a single Client instance is updated with several services, resulting in output based on the current property value.
Output
Service1 Called
Service2 Called
2. Property/Setter Injection
- Property/Setter injection is a sort of dependency injection in which dependencies are passed to a class via public properties or setter methods after the object has been created.
- This technique provides for optional dependencies and allows you to change them at runtime without having to create new instances, which promotes flexibility and ease of maintenance.
The steps to construct Dependency Injection utilizing property/setter injection in C# are as follows:
- Define Interfaces: Create interfaces for the dependencies that your class needs.
- Implement Interfaces: Provide actual implementations for these interfaces.
- Use Property/Setter Injection: Incorporate dependencies into the class using public properties or setter methods.
- Set up the DI Container: Configure a DI container, like Microsoft.Extensions.DependencyInjection manages and resolves dependencies.
- Resolve dependencies: Retrieve objects from the container, set their properties, or use setters to inject.
Example
using System;
public interface IService {
void Serve();
}
public class Service1 : IService {
public void Serve() {
Console.WriteLine("Service1 Called");
}
}
public class Service2 : IService {
public void Serve() {
Console.WriteLine("Service2 Called");
}
}
public class Client {
private IService _service;
public IService Service {
set { this._service = value; }
}
public void ServeMethod() {
this._service.Serve();
}
}
class Program {
static void Main(string[] args) {
// Creating object
Service1 s1 = new Service1();
Client client = new Client();
client.Service = s1; // Passing dependency
client.ServeMethod();
Service2 s2 = new Service2();
client.Service = s2; // Passing dependency
client.ServeMethod();
}
}
Explanation
This code shows property injection by using the Client class's Service property to dynamically inject different IService implementations (Service1 and Service2), allowing the ServeMethod to call the appropriate Serve function based on the injected service.
Output
Service1 Called
Service2 Called
3. Method Injection
- Method injection is a sort of dependency injection in which dependencies are passed to a class via method parameters.
- This technique allows dependencies to be injected only when necessary, providing flexibility in managing and modifying dependencies without affecting the object's state.
The steps for implementing Dependency Injection with method injection in C# are as follows:
- Define Interfaces: Create interfaces for the dependencies your class requires.
- Implement Interfaces: Provide concrete implementations for these interfaces.
- Use Method Injection: Inject dependencies into the class using method parameters.
- Set a DI Container: Configure a DI container like Microsoft.Extensions.Dependency injection is used to manage and resolve dependencies as needed.
- Resolve Dependencies: Extract instances from the container and send them as arguments to methods that require these dependencies.
Example
public interface IService {
void Serve();
}
public class Service1 : IService {
public void Serve() {
Console.WriteLine("Service1 Called");
}
}
public class Service2 : IService {
public void Serve() {
Console.WriteLine("Service2 Called");
}
}
public class Client {
public void ServeMethod(IService service) {
service.Serve();
}
}
class Program
{
static void Main(string[] args)
{
// Creating object
Service1 s1 = new Service1();
Client client = new Client();
// Passing dependency
client.ServeMethod(s1); // Calls Service1.Serve(), outputs: "Service1 Called"
Service2 s2 = new Service2();
client.ServeMethod(s2); // Calls Service2.Serve(), outputs: "Service2 Called"
}
}
Explanation
This code shows method injection by having the Client class's ServeMethod directly receive and use different IService implementations (Service1 and Service2) as method parameters, which allows for dynamic dependency management.
Output
Service1 Called
Service2 Called
Advantages of Dependency Injection in C#
Here are some major benefits of dependency injection in C#:
- Improved Testability: Dependencies can be readily mocked or stubbed, making unit testing more simple and effective.
- Enhanced Flexibility: Enables the injection of multiple implementations at runtime without modifying the client code, resulting in more adaptability.
- Decoupling of Components: Reduces tight coupling between classes, making the software more modular and maintainable.
- Simplified Object generation: Centralizes dependency generation and management, typically employing a DI container to handle complex object graphs and lifecycle management.
- Support for Multiple Configurations: Allows for quick swapping of implementations or configurations by changing DI container settings or constructor arguments.
DI Container
- A Dependency Injection (DI) container is a framework or library that handles the lifespan and resolution of dependencies within an application.
- It automates the process of building and injecting dependencies, allowing developers to specify how objects should be built and the dependencies they require.
- A DI container encourages loose coupling, enhances testability, and simplifies configuration changes by centralizing object generation and dependency resolution, making complicated object graphs easier to manage and a clean, modular codebase to maintain.
Read More: What is IoC Container or DI Container |
Summary
Dependency Injection is a design pattern in C# that improves flexibility, testability, and maintainability by injecting dependencies into classes rather than hard-coding them. It offers a variety of injection mechanisms, including constructor, property/setter, and method, to facilitate dynamic dependency management and modular architecture. Also, consider our .NET design patterns training for a better understanding of other design patterns concepts.
FAQs
By supplying the DEPENDENCY through the class's constructor when creating the instance of that class.
Factory Pattern, Template Method Design Pattern, Strategy Pattern and Service Locator pattern too
The dependency inversion principle