Dependency Injection in .NET using C#
--
This article is a part of Design Pattern notebook by Fariz Mamad
It is common if a class depends on other classes. Favorably, classes are loosely-coupled from their dependencies to make it more testable, modular, and maintainable. Loosely-coupled application can be achieved if we follow Dependency Inversion Principle.
Dependency Injection (DI) is a design pattern that developers use to achieve Dependency Inversion principle between classes and their dependencies.
The following code snippet will be a showcase to use dependency injection in .NET using C# language, which supports Dependency Injection. Moreover, it provides service container for registering dependencies, and is responsible for creating and disposing instance of dependency.
/**
MessageWriter class is the dependency of the Worker class
source: https://docs.microsoft.com/en-us/dotnet/core/exteDependency injection in .NET | Microsoft Docsnsions/dependency-injection
*/
public class MessageWriter {
public void Write(string message) {
Console.WriteLine($"MessageWriter.Write(message: \"{message}\")");
}
}
public class Worker : BackgroundService {
private readonly MessageWriter _messageWriter = new MessageWriter(); protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
while (!stoppingToken.IsCancellation Requested) {
_messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
await Task. Delay(1000, stoppingToken);
}
}
}
What are the problems?
- Changing MessageWriter class implementation require Worker class modification.
- Worker class is responsible to configure dependencies of MessageWriter class, which makes the code scattered.
- Impossible to use mock MessageWriter in unit test.
How to solve these issues using DI?
- Create interface, e.g. IMessageWriter.
- Register it with concrete implementation MessageWriter class to the service container.
- Worker class request for IMessageWriter. The DI container will provide the instance.
Code Snippets
- Create interface, e.g. IMessageWriter.
/**
Create interface IMessageWriter and rewrite MessageWriter to implement IMessageWriter
source: https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
*/
using System;
namespace DependencyInjection.Example {
public interface IMessageWriter {
void Write(string message);
}
}namespace DependencyInjection.Example {
public class MessageWriter : IMessageWriter {
public void Write(string message) {
Console.WriteLine($"MessageWriter.Write(message: \"{message}\")");
}
}
}
2. Then, register the interface and concrete implementation to the service container.
/**
Register to the service container with its concrete implementation MessageWriter
source: https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
*/using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;namespace DependencyInjection.Example {
class Program {
static Task Main(string[] args) => CreateHostBuilder (args).Build().RunAsync();static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureServices((_, services) => services.AddHostedService<Worker>().AddScoped<IMessageWriter, MessageWriter>());
}
}
3. Worker class request for IMessageWriter. The DI container will provide the instance.
/**
Worker class request for IMessageRequest. The DI container will provide the instance.
source: https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection
*/
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting; namespace DependencyInjection.Example {
public class Worker : BackgroundService {
private readonly IMessageWriter _messageWriter;
public Worker (IMessageWriter messageWriter) => _messageWriter = messageWriter; protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
while (!stoppingToken.IsCancellationRequested) {
_messageWriter.Write($"Worker running at: {DateTimeOffset. Now}");
await Task. Delay(1000, stoppingToken);
}
}
}
}
At this point, we have successfully implementing Dependency Injection in .NET using C# language.
References: