Chargement...

Principes de l’Injection de Dépendances en C#

Apprenez les principes de l’Injection de Dépendances en C#, la gestion des dépendances et le couplage faible avec exemples.

En développement logiciel, l’Injection de Dépendances (DI) est un modèle de conception important utilisé pour gérer les dépendances. Avec la DI, les classes reçoivent les objets dont elles ont besoin depuis l’extérieur au lieu de les créer en interne. Cela rend le code plus flexible, testable et maintenable. Dans l’écosystème C# et .NET Core, la DI est prise en charge nativement.


Qu’est-ce qu’une dépendance ?

Une classe dépend d’une autre lorsqu’elle a besoin de sa fonctionnalité. Par exemple, un OrderService peut nécessiter une instance de ILogger lors de la création d’une commande. Si OrderService utilise directement new Logger(), il devient fortement couplé à la classe Logger.


public class OrderService
{
    private readonly Logger _logger = new Logger();

    public void CreateOrder(string product)
    {
        _logger.Log($"Commande créée : {product}");
    }
}

public class Logger
{
    public void Log(string message) => Console.WriteLine(message);
}

Avec cette approche, le Logger ne peut pas être remplacé. Si vous souhaitez utiliser un autre système de journalisation, vous devez modifier le code de OrderService. C’est précisément là que l’Injection de Dépendances intervient.


Solution avec l’Injection de Dépendances

Avec la DI, les dépendances sont abstraites et fournies de l’extérieur (par le constructeur ou les paramètres de méthode). Ainsi, OrderService dépend de l’interface ILogger, et le monde extérieur décide quel logger utiliser.


public interface ILogger
{
    void Log(string message);
}

public class ConsoleLogger : ILogger
{
    public void Log(string message) => Console.WriteLine("[Console] " + message);
}

public class FileLogger : ILogger
{
    public void Log(string message) => 
        System.IO.File.AppendAllText("log.txt", message + "\n");
}

public class OrderService
{
    private readonly ILogger _logger;

    // Injection par constructeur
    public OrderService(ILogger logger)
    {
        _logger = logger;
    }

    public void CreateOrder(string product)
    {
        _logger.Log($"Commande créée : {product}");
    }
}

class Program
{
    static void Main()
    {
        // Différents loggers peuvent être choisis
        ILogger logger = new ConsoleLogger();
        var service = new OrderService(logger);

        service.CreateOrder("Ordinateur portable");
    }
}

Dans cet exemple, OrderService n’est plus lié à une classe Logger spécifique ; il ne dépend que de l’interface ILogger. Ainsi, ConsoleLogger ou FileLogger peuvent être utilisés facilement.


Types d’Injection de Dépendances


Utilisation de la DI dans .NET Core

Dans les applications .NET Core, un conteneur DI intégré est disponible. Les services sont enregistrés dans Program.cs ou Startup.cs, et sont injectés automatiquement dans les classes qui en ont besoin.


var builder = WebApplication.CreateBuilder(args);

// Enregistrer les services
builder.Services.AddScoped<ILogger, ConsoleLogger>();
builder.Services.AddScoped<OrderService>();

var app = builder.Build();

app.MapGet("/order", (OrderService service) =>
{
    service.CreateOrder("Téléphone");
    return "Commande traitée.";
});

app.Run();

Ici, le conteneur DI crée automatiquement une instance de ConsoleLogger pour OrderService et l’injecte.


Avantages


TL;DR

  • Injection de Dépendances : Les classes reçoivent les objets dont elles ont besoin depuis l’extérieur.
  • Injection par constructeur : La méthode la plus courante ; les dépendances sont fournies via le constructeur.
  • .NET Core : Fournit un conteneur DI intégré.
  • Avantages : Offre une architecture plus flexible, testable et facile à maintenir.

Articles connexes