Dependency Injection in .NET using C#

fariz mamad
2 min readJul 8, 2022

--

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?

  1. Changing MessageWriter class implementation require Worker class modification.
  2. Worker class is responsible to configure dependencies of MessageWriter class, which makes the code scattered.
  3. Impossible to use mock MessageWriter in unit test.

How to solve these issues using DI?

  1. Create interface, e.g. IMessageWriter.
  2. Register it with concrete implementation MessageWriter class to the service container.
  3. Worker class request for IMessageWriter. The DI container will provide the instance.

Code Snippets

  1. 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:

  1. Dependency injection in .NET | Microsoft Docs

--

--

fariz mamad

Write about software engineering and career