vendredi 22 novembre 2024

Dependency Injection

 Le design pattern Dependency Injection (DI) est une technique de conception dans laquelle les dépendances d'un objet sont injectées plutôt que créées à l'intérieur de cet objet. L'objectif est de rendre un objet indépendant des détails de l'implémentation de ses dépendances, ce qui améliore la modularité, la testabilité et la réutilisabilité du code.

En C#, l'injection de dépendances est souvent mise en œuvre en utilisant des frameworks d'injection de dépendances tels que ASP.NET Core DI, Ninject, Unity, etc., ou même manuellement en passant les dépendances via les constructeurs, propriétés ou méthodes.

Voici un exemple simple d'injection de dépendances en C# sans utiliser de framework externe :

```csharp

using System;

// Interface représentant une dépendance

public interface ILogger

{

void Log(string message);

}

// Implémentation concrète de la dépendance

public class ConsoleLogger : ILogger

{

public void Log(string message)

{

Console.WriteLine($"[Console Logger] {message}");

}

}

// Classe utilisant l'injection de dépendances

public class OrderProcessor

{

private readonly ILogger logger;

// Injection de dépendance via le constructeur

public OrderProcessor(ILogger logger)

{

this.logger = logger;

}

public void ProcessOrder(string orderInfo)

{

// Logique métier de traitement de la commande

logger.Log($"Processing order: {orderInfo}");

}

}

class Program

{

static void Main()

{

// Configuration et injection des dépendances manuellement

ILogger consoleLogger = new ConsoleLogger();

OrderProcessor orderProcessor = new OrderProcessor(consoleLogger);

// Utilisation de la classe avec les dépendances injectées

orderProcessor.ProcessOrder("12345");

}

}

```

Dans cet exemple, `OrderProcessor` dépend de `ILogger`, mais au lieu de créer directement une instance de `ConsoleLogger` à l'intérieur de `OrderProcessor`, nous passons l'instance requise via le constructeur. Cela permet de remplacer facilement l'implémentation de `ILogger` sans modifier `OrderProcessor`, ce qui rend le code plus souple et facile à tester.


============== Dependency Injection =================


L'injection de dépendances (Dependency Injection, ou DI) est une technique utilisée pour rendre vos applications C# plus modulaires et testables en séparant la création des objets de leur utilisation. Cette approche repose souvent sur un conteneur d'inversion de contrôle (IoC) pour gérer les dépendances automatiquement.


1. Frameworks pour l'injection de dépendances

En C#, plusieurs frameworks prennent en charge l'injection de dépendances. Les plus courants sont :

1.1 Microsoft.Extensions.DependencyInjection

  • Framework natif de .NET (disponible dans .NET Core et .NET 5+).
  • Léger, simple à configurer.
  • Souvent utilisé avec ASP.NET Core.

1.2 Autres frameworks populaires

  • Autofac : plus riche en fonctionnalités (cycles de vie complexes, modularité).
  • Ninject : facile à utiliser, bien que plus lourd.
  • Castle Windsor : adapté aux projets complexes nécessitant des conteneurs puissants.
  • Unity : utilisé historiquement, mais moins populaire aujourd'hui.

Pour débuter ou pour des projets .NET modernes, Microsoft.Extensions.DependencyInjection est recommandé.


2. Principes de base de l'injection de dépendances

2.1 Types d'injection :

  1. Injection par constructeur (recommandée)
    Les dépendances sont passées dans le constructeur de la classe.

  2. Injection par propriété
    Les dépendances sont affectées via des propriétés publiques.

  3. Injection par méthode
    Les dépendances sont fournies à une méthode spécifique lors de l'appel.


3. Exemple avec Microsoft.Extensions.DependencyInjection

Étape 1 : Configuration du conteneur DI

Commencez par ajouter le package :

dotnet add package Microsoft.Extensions.DependencyInjection

Ensuite, configurez vos services :

using Microsoft.Extensions.DependencyInjection;
using System;

public interface IMessageService
{
    void SendMessage(string message);
}

public class EmailService : IMessageService
{
    public void SendMessage(string message)
    {
        Console.WriteLine($"Email sent: {message}");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 1. Créer un conteneur DI
        var services = new ServiceCollection();

        // 2. Enregistrer des services dans le conteneur
        services.AddTransient<IMessageService, EmailService>(); // Liaison interface/implémentation

        // 3. Construire le conteneur
        var serviceProvider = services.BuildServiceProvider();

        // 4. Résoudre et utiliser le service
        var messageService = serviceProvider.GetService<IMessageService>();
        messageService.SendMessage("Hello, Dependency Injection!");
    }
}

Étape 2 : Modes de durée de vie (lifetimes)

Lors de l’enregistrement d’un service, vous pouvez spécifier sa durée de vie :

  • AddTransient : une nouvelle instance à chaque demande.
  • AddScoped : une instance par scope (utile dans ASP.NET pour une requête HTTP).
  • AddSingleton : une seule instance pour l'application entière.


4. Utilisation dans ASP.NET Core

ASP.NET Core intègre le conteneur DI par défaut. Voici un exemple :

Configuration dans Program.cs

var builder = WebApplication.CreateBuilder(args);

// Enregistrer des services dans le conteneur
builder.Services.AddScoped<IMessageService, EmailService>();

var app = builder.Build();

// Utiliser un service
app.MapGet("/", (IMessageService messageService) =>
{
    messageService.SendMessage("Hello from ASP.NET Core!");
    return Results.Ok();
});

app.Run();


5. Pourquoi utiliser un framework DI ?

  • Découplage : Les classes dépendent d’interfaces, et non d’implémentations concrètes.
  • Testabilité : Vous pouvez injecter des dépendances simulées (mock) dans les tests unitaires.
  • Gestion centralisée des dépendances : Plus facile de contrôler la création et la durée de vie des objets.

Pour des applications modernes, Microsoft.Extensions.DependencyInjection est souvent suffisant. Si vous avez des besoins avancés (cycles complexes, modules), envisagez Autofac.

Aucun commentaire:

Enregistrer un commentaire