13
SepImplementation of Dependency Injection In C#
Dependency Injection
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#?
- 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.
- 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
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
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.
- 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
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.
- 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
Output
Service1 Called
Service2 Called
Advantages 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.
- 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 |