C# & .NET
Comprendre les classes, les interfaces et l'injection de dépendances
Les objets portent le comportement. Les interfaces définissent les contrats. L'injection de dépendances relie les composants explicitement.
// vous allez apprendre
- Distinguer contrat et implémentation
- Injecter par le constructeur
- Choisir une durée de vie adaptée
// avant de commencer
- Variables, méthodes et syntaxe C# de base
Partir du comportement
Une classe regroupe un état et des comportements. Une interface décrit ce qu'un collaborateur sait faire sans imposer son implémentation. Injecter une dépendance consiste à recevoir ce collaborateur plutôt qu'à le construire dans la classe qui l'utilise.
Rendre la dépendance visible
public interface IMessageSender
{
Task SendAsync(string message, CancellationToken token);
}
public sealed class NotificationService(IMessageSender sender)
{
public Task NotifyAsync(CancellationToken token) =>
sender.SendAsync("Your report is ready.", token);
}
// In an ASP.NET Core composition root:
builder.Services.AddScoped<IMessageSender, EmailSender>();
builder.Services.AddScoped<NotificationService>();EmailSender doit implémenter IMessageSender. L'enregistrement se fait à la racine de composition, là où l'application assemble ses implémentations concrètes. Le service de notification n'a pas à connaître les paramètres SMTP ni les identifiants du fournisseur.
Choisir la durée de vie
Une dépendance transitoire est créée à chaque demande. Une dépendance de portée vit pendant une portée, généralement une requête HTTP. Un singleton vit pendant toute l'application. Un singleton ne doit pas capturer un contexte de base de données de portée plus courte.
Tester le contrat
Fournissez un faux expéditeur qui enregistre le message. Vérifiez que le service envoie une seule fois le texte attendu et transmet l'annulation. Aucun serveur de messagerie n'est nécessaire.
À vous de jouer
- Implémentez un expéditeur console.
- Construisez le service manuellement, sans conteneur.
- Remplacez l'expéditeur dans un test.
- Expliquez pourquoi le conteneur est pratique mais non indispensable.
Ne créez pas systématiquement une interface pour chaque classe. Une frontière doit clarifier une responsabilité ou offrir une alternative utile.