Dependency Injection in C#: Vollständiger Leitfaden mit Beispielen

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

Dependency Injection in C#: was es ist und warum man es braucht



Dependency Injection (DI) ist eines der wichtigsten Entwurfsmuster, das es ermöglicht, lose gekoppelte und leicht testbare Anwendungen in C# zu erstellen. Anstatt dass eine Klasse ihre Abhängigkeiten selbst erstellt (z. B. Objekte für die Datenbankarbeit oder Protokollierung), werden diese Abhängigkeiten von außen übergeben (injiziert). Dies realisiert das Prinzip Inversion of Control (IoC) – die Kontrolle wird an einen externen Container übergeben.



Im .NET-Ökosystem ist DI seit ASP.NET Core zum De-facto-Standard geworden. Der integrierte Abhängigkeitscontainer (über Microsoft.Extensions.DependencyInjection) ermöglicht es, Abhängigkeiten einfach zu registrieren und aufzulösen. In diesem Artikel werden wir die Theorie, praktische Beispiele und bewährte Methoden zur Verwendung von DI in C# behandeln.



Grundprinzipien der Dependency Injection



DI basiert auf drei grundlegenden Methoden der Abhängigkeitsinjektion. Betrachten wir jede davon.



1. Injektion über den Konstruktor

Die gebräuchlichste und bevorzugte Methode. Abhängigkeiten werden über die Parameter des Klassenkonstruktors übergeben.



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

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

public class OrderService{ private readonly ILogger _logger;

// Abhängigkeitsinjektion über den Konstruktor public OrderService(ILogger logger) { _logger = logger; }

public void ProcessOrder(int orderId) { _logger.Log($"Verarbeitung der Bestellung {orderId}"); // Geschäftslogik }}


2. Injektion über eine Eigenschaft

Die Abhängigkeit wird über eine öffentliche Eigenschaft gesetzt. Weniger bevorzugt, da es die Abhängigkeit optional macht und zu Laufzeitfehlern führen kann.



public class OrderService{    public ILogger Logger { get; set; }

public void ProcessOrder(int orderId) { if (Logger == null) throw new InvalidOperationException("Logger wurde nicht gesetzt"); Logger.Log($"Verarbeitung der Bestellung {orderId}"); }}


3. Injektion über eine Methode

Die Abhängigkeit wird als Methodenparameter übergeben. Wird selten verwendet, normalerweise für temporäre Abhängigkeiten.



public class OrderService{    public void ProcessOrder(int orderId, ILogger logger)    {        logger.Log($"Verarbeitung der Bestellung {orderId}");    }}


Registrierung von Abhängigkeiten im .NET-Container



Im modernen .NET (ASP.NET Core, Console, Worker Services) wird der integrierte DI-Container verwendet. Die Registrierung erfolgt in der Methode ConfigureServices oder beim Erstellen einer ServiceCollection.



Es gibt drei Lebensdauern (lifetimes) für registrierte Dienste:



  • Transient – Bei jeder Anforderung wird eine neue Instanz erstellt. Geeignet für leichte, kurzlebige Dienste.
  • Scoped – Eine Instanz pro HTTP-Anfrage (oder Scope). Wird für Entity Framework DbContext verwendet.
  • Singleton – Eine Instanz für die gesamte Anwendung. Geeignet für Caches, Einstellungen, Logger.


// Beispiel für ASP.NET Corepublic class Startup{    public void ConfigureServices(IServiceCollection services)    {        // Registrierung mit Schnittstelle        services.AddTransient<ILogger, ConsoleLogger>();        services.AddScoped<IOrderRepository, OrderRepository>();        services.AddSingleton<IConfiguration, ConfigurationManager>();

// Registrierung ohne Schnittstelle (konkrete Klasse) services.AddTransient<OrderService>(); }}

// Verwendung im Controllerpublic class OrderController : ControllerBase{ private readonly OrderService _orderService;

public OrderController(OrderServi

Blogs

Buchempfehlungen