Injection de dépendances en C# : guide pratique avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : qu'est-ce que l'injection de dépendances et pourquoi en a-t-on besoin

\n

L'injection de dépendances (DI) est l'un des patrons de conception clés qui implémente le principe d'inversion des dépendances (Dependency Inversion Principle) de SOLID. En pratique, cela signifie que les objets ne créent pas leurs dépendances eux-mêmes, mais les reçoivent de l'extérieur. Cela rend le code flexible, testable et faiblement couplé.

\n

Dans l'écosystème C# et .NET, la DI est devenue un standard de facto. Depuis .NET Core, la plateforme intègre son propre conteneur d'injection de dépendances, utilisé dans ASP.NET Core, les services d'arrière-plan et même les applications console. Sans comprendre la DI, il est impossible d'imaginer le développement moderne en C#.

\n

Dans cet article, nous analyserons la DI avec des exemples concrets : de l'injection manuelle à l'utilisation du conteneur intégré .NET. Vous verrez comment vous débarrasser des couplages rigides et rendre le code adapté aux tests unitaires.

\n\n

Le problème sans injection de dépendances

\n

Imaginons un scénario typique : la classe OrderService traite les commandes et envoie des notifications par email. Sans DI, le code ressemble à ceci :

\n
public class EmailSender\n{\n    public void Send(string to, string subject, string body)\n    {\n        Console.WriteLine($"Envoi d'email à {to} : {subject}");\n    }\n}\n\npublic class OrderService\n{\n    private EmailSender _emailSender;\n\n    public OrderService()\n    {\n        // Couplage rigide — la classe crée elle-même la dépendance\n        _emailSender = new EmailSender();\n    }\n\n    public void ProcessOrder(int orderId)\n    {\n        // Logique de traitement de la commande...\n        _emailSender.Send("user@example.com", "Commande confirmée", $"Votre commande #{orderId} a été acceptée.");\n    }\n}
\n

Quel est le problème ? OrderService est fortement lié à l'implémentation concrète EmailSender. Si nous voulons remplacer l'envoi d'email par des SMS ou de la journalisation, il faudra modifier le code de OrderService. Les tests sont également plus complexes : impossible de substituer le vrai EmailSender par un objet mock.

\n\n

Solution : injection de dépendances par constructeur

\n

La première étape vers la DI est d'extraire une abstraction (interface) et de passer la dépendance via le constructeur. C'est ce qu'on appelle l'injection par constructeur (Constructor Injection).

\n\n

Étape 1 : Créer l'interface

\n
public interface INotificationService\n{\n    void Send(string to, string subject, string body);\n}
\n\n

Étape 2 : Implémenter l'interface

\n
public class EmailSender : INotificationService\n{\n    public void Send(string to, string subject, string body)\n    {\n        Console.WriteLine($"Email envoyé : {subject} -> {to}");\n    }\n}\n\npublic class SmsSender : INotificationService\n{\n    public void Send(string to, string subject, string body)\n    {\n        Console.WriteLine($"SMS envoyé : {subject} -> {to}");\n    }\n}
\n\n

Étape 3 : Injecter la dépendance via le constructeur

\n
public class OrderService\n{\n    private readonly INotificationService _notificationService;\n\n    // La dépendance est transmise de l'extérieur\n    public OrderService(INotificationService notificationService)\n    {\n        _notificationService = notificationService;\n    }\n\n    public void ProcessOrder(int orderId)\n    {\n        // Logique de traitement de la commande...\n        _notificationService.Send("user@example.com", "Commande confirmée", $"Votre commande #{orderId} a été acceptée.");\n    }\n}
\n

Désormais, OrderService ne sait pas quelle implémentation est utilisée. Nous pouvons lui fournir EmailSender, SmsSender ou toute autre classe implémentant INotificationService. Le code est devenu flexible et testable.

\n\n

Utilisation du conteneur IoC intégré dans .NET

\n

Créer manuellement toutes les dépendances n'est pas pratique. .NET dispose d'un conteneur intégré (conteneur IoC) qui gère automatiquement le cycle de vie des objets. Prenons un exemple pour une application console.

\n\n

Étape 1 : Installer le paquet

Blogs

Book Recommendations