Abhängigkeitsinjektion (Dependency Injection) in C#: Vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Was ist Dependency Injection in C# und warum wird es benötigt



In der modernen Entwicklung mit C# und .NET ist eines der wichtigsten Entwurfsprinzipien Dependency Injection (DI) – die Abhängigkeitsinjektion. Dieses Muster ermöglicht die Erstellung von lose gekoppeltem, testbarem und leicht wartbarem Code. Anstatt dass eine Klasse selbst Instanzen der benötigten Objekte erstellt (feste Kopplung), werden die Abhängigkeiten von außen injiziert.



Das Hauptziel von DI ist die Umsetzung des Prinzips Inversion of Control (IoC), bei dem die Kontrolle über die Objekterstellung an einen externen Container oder ein Framework übergeben wird. Dies verändert die Architektur der Anwendung grundlegend und macht sie flexibel und anpassungsfähig für Änderungen.



Das Problem der festen Kopplung (Tight Coupling)



Betrachten wir ein typisches Beispiel ohne DI:



public class OrderService{    private readonly EmailSender _emailSender;

public OrderService() { // Feste Abhängigkeit – wir erstellen eine Instanz einer konkreten Klasse _emailSender = new EmailSender(); }

public void ProcessOrder(Order order) { // Logik zur Auftragsverarbeitung _emailSender.Send("Auftrag verarbeitet"); }}


Hier ist OrderService direkt von EmailSender abhängig. Wenn wir den E-Mail-Versand durch SMS oder Logging ersetzen möchten, müssten wir den Code von OrderService ändern. Dies verletzt das Open/Closed-Prinzip und macht Modultests praktisch unmöglich.



Grundlegende Methoden der Abhängigkeitsinjektion in C#



In C# gibt es drei Hauptmethoden zur Implementierung von DI. Jede hat ihre eigenen Anwendungsszenarien und Besonderheiten.



1. Injektion über den Konstruktor (Constructor Injection)



Dies ist die beliebteste und empfohlene Methode in .NET. Die Abhängigkeiten werden über die Konstruktorparameter übergeben und normalerweise in privaten, schreibgeschützten Feldern (readonly) gespeichert.



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

public class EmailService : INotificationService{ public void Send(string message) { Console.WriteLine($"E-Mail gesendet: {message}"); }}

public class OrderService{ private readonly INotificationService _notificationService;

// Die Abhängigkeit wird über den Konstruktor injiziert public OrderService(INotificationService notificationService) { _notificationService = notificationService; }

public void ProcessOrder(Order order) { // Logik... _notificationService.Send("Auftrag verarbeitet"); }}


Vorteile: Es ist klar ersichtlich, welche Abhängigkeiten die Klasse benötigt; die Abhängigkeiten sind nach der Objekterstellung unveränderlich; leicht testbar durch das Einsetzen von Mock-Objekten.



2. Injektion über eine Eigenschaft (Property Injection)



Die Abhängigkeit wird über eine öffentliche Eigenschaft (Setter) gesetzt. Wird seltener verwendet, wenn die Abhängigkeit für die Arbeit der Klasse nicht zwingend erforderlich ist.



public class OrderService{    public INotificationService NotificationService { get; set; }

public OrderService() { }

public void ProcessOrder(Order order) { if (NotificationService != null) { NotificationService.Send("Auftrag verarbeitet"); } }}


Nachteil: Man kann vergessen, die Abhängigkeit zu setzen, was zur Laufzeit zu einer NullReferenceException führt. Sollte nur für optionale Abhängigkeiten verwendet werden.



3. Injektion über eine Methode (Method Injection)



Die Abhängigkeit wird direkt an die Methode übergeben, in der sie verwendet wird. Dies ist praktisch, wenn die Abhängigkeit nur für eine bestimmte Aktion benötigt wird.



public class OrderService{    public void ProcessOrder(Order order, INotificationService notificationService)    {        // Logik...        notificat                

Blogs

Buchempfehlungen