Menu
Coddy logo textTech

Bases de l'Injection de Dépendances

Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy. Leçon 46 sur 70.

Injection de dépendances (DI) est une technique dans laquelle une classe reçoit ses dépendances de l’extérieur au lieu de les créer elle-même. Cela rend le code plus flexible, testable et faiblement couplé.

Sans DI, une classe crée ses propres dépendances, ce qui rend leur modification ou leur test difficiles :

public class OrderService
{
    private EmailSender sender = new EmailSender();  // Fortement couplé
    
    public void PlaceOrder() => sender.Send("Order placed");
}

Avec l’injection de dépendances (DI), les dépendances sont transmises via le constructeur :

public interface IMessageSender
{
    void Send(string message);
}

public class EmailSender : IMessageSender
{
    public void Send(string message) => Console.WriteLine("Email: " + message);
}

public class OrderService
{
    private IMessageSender sender;
    
    public OrderService(IMessageSender sender)
    {
        this.sender = sender;
    }
    
    public void PlaceOrder() => sender.Send("Order placed");
}

Désormais, OrderService ne sait pas et ne se soucie pas de savoir s’il utilise un expéditeur d’e-mails, de SMS ou un expéditeur simulé pour les tests. La dépendance est « injectée » lors de la création de l’objet :

IMessageSender emailSender = new EmailSender();
OrderService service = new OrderService(emailSender);
service.PlaceOrder();  // Email : Commande passée

Ce modèle suit le principe de dépendre des abstractions (interfaces) plutôt que des implémentations concrètes. Il permet de remplacer les implémentations sans modifier la classe qui les utilise, ce qui est essentiel pour les tests unitaires et la maintenance d’architectures flexibles.

challenge icon

Défi

Facile

Construisons un système de journalisation qui démontre la puissance de l’injection de dépendances. Au lieu de coder en dur la manière dont les journaux sont écrits, vous allez créer une classe Logger flexible, capable de fonctionner avec n’importe quelle destination de journalisation — console, simulation de fichier ou autre — sans connaître les détails spécifiques.

Vous allez organiser votre code sur trois fichiers :

  • ILogWriter.cs : définissez une interface appelée ILogWriter dans l’espace de noms Logging. Cette interface représente le contrat de toute destination de journalisation et doit comporter une seule méthode Write(string message) qui renvoie une chaîne décrivant l’endroit où le message a été écrit.
  • LogWriters.cs : créez deux implémentations concrètes de ILogWriter dans l’espace de noms Logging :
    • ConsoleLogWriter — sa méthode Write renvoie Console: {message}
    • FileLogWriter — reçoit un nom de fichier via son constructeur et sa méthode Write renvoie File[{filename}]: {message}
  • Logger.cs : créez une classe Logger dans l’espace de noms Logging qui reçoit sa dépendance par injection via le constructeur. La classe Logger doit :
    • Accepter un ILogWriter via son constructeur et le stocker dans un champ privé
    • Disposer d’une méthode Log(string message) qui délègue l’opération au générateur de journaux injecté et renvoie le résultat
  • Program.cs : démontrez l’injection de dépendances en créant deux générateurs de journaux différents — l’un avec un ConsoleLogWriter et l’autre avec un FileLogWriter. Montrez comment la même classe Logger se comporte différemment selon la dépendance injectée.

Vous recevrez deux entrées :

  • Le nom de fichier pour le générateur de journaux de fichier
  • Le message à journaliser

Créez un Logger avec un ConsoleLogWriter et journalisez le message. Créez ensuite un autre Logger avec un FileLogWriter (en utilisant le nom de fichier fourni en entrée) et journalisez le même message. Affichez chaque résultat sur sa propre ligne.

Par exemple, si les entrées sont app.log et System started, la sortie doit être :

Console: System started
File[app.log]: System started

Remarquez que la classe Logger ne change jamais : elle fonctionne avec toute implémentation de ILogWriter. C’est l’essence de l’injection de dépendances : Logger dépend d’une abstraction (l’interface), et l’implémentation concrète est « injectée » depuis l’extérieur. Vous pourriez facilement ajouter plus tard un DatabaseLogWriter ou un CloudLogWriter sans modifier du tout la classe Logger !

Essayez vous-même

using System;
using Logging;

class Program
{
    public static void Main(string[] args)
    {
        // Lire les entrées
        string filename = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: Créer un Logger avec un ConsoleLogWriter et journaliser le message
        // Afficher le résultat

        // TODO: Créer un autre Logger avec un FileLogWriter (en utilisant le filename) et journaliser le même message
        // Afficher le résultat
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C# en ligne