Webframeworkk/ASP.NET Core/Dependency Inversion: Unterschied zwischen den Versionen

Aus Dokument
Zur Navigation springen Zur Suche springen
Die Seite wurde neu angelegt: „ == 1. Was sind View Components? == View Components (Ansichtskomponenten) sind eigenständige, wiederverwendbare UI-Bausteine in ASP.NET Core MVC. Sie sind dafür konzipiert, Rendering-Logik zu kapseln, die komplexer ist als das, was man typischerweise in eine Partial View (Teilansicht) packen würde, aber nicht die Komplexität eines vollwertigen Controllers rechtfertigt. === Hauptmerkmale === * '''Komplexität kapseln''': Gruppieren Sie zusammenhängen…“
 
Keine Bearbeitungszusammenfassung
 
(Eine dazwischenliegende Version von einem anderen Benutzer wird nicht angezeigt)
Zeile 3: Zeile 3:




== 1. Was sind View Components? ==
== 1. Einführung: Was sind Services? ==
View Components (Ansichtskomponenten) sind eigenständige, wiederverwendbare UI-Bausteine in ASP.NET Core MVC. Sie sind dafür konzipiert, Rendering-Logik zu kapseln, die komplexer ist als das, was man typischerweise in eine Partial View (Teilansicht) packen würde, aber nicht die Komplexität eines vollwertigen Controllers rechtfertigt.


=== Hauptmerkmale ===
In ASP.NET Core MVC sind '''Services''' Klassen, die für die Implementierung der Kern-Geschäftslogik Ihrer Anwendung verantwortlich sind. Sie sind darauf ausgelegt, wiederverwendbar, eigenständig und unabhängig von spezifischen Controllern oder Views zu sein.
* '''Komplexität kapseln''': Gruppieren Sie zusammenhängende UI-Rendering-Logik in einer zusammenhängenden Einheit.
* '''Wiederverwendbarkeit''': Verwenden Sie View Components in mehreren Ansichten, um Code-Duplizierung zu vermeiden.
* '''Testbarkeit''': Aufgrund ihrer eigenständigen Natur leichter per Unit Test zu testen.
* '''Rendering-Logik''': Ideal für dynamische Widgets, Navigationsmenüs, Login-Formulare, Warenkorb-Zusammenfassungen oder jedes UI-Element, das Datenabrufe oder Logik vor dem Rendern erfordert.


=== Wann man View Components verwendet ===
=== Hauptaufgaben von Services ===
* '''Komplexe UI-Elemente''': Wenn ein UI-Element komplexe Rendering-Logik erfordert.
* '''Kapselung der Geschäftslogik''': Trennung komplexer Operationen von der Präsentationsschicht (Controller/Views).
* '''Datengetriebene Elemente''': Wenn Sie Daten abrufen oder Berechnungen durchführen müssen, bevor gerendert wird.
* '''Wiederverwendbarkeit''': Ein Service kann von mehreren Controllern genutzt werden (DRY-Prinzip).
* '''Wiederverwendbare Widgets''': Wenn Sie ein wiederverwendbares Widget für verschiedene Teile Ihrer Anwendung erstellen möchten.
* '''Testbarkeit''': Services können leicht isoliert getestet werden (Unit Tests).
* '''Datenzugriff''': Kommunikation mit Datenbanken oder APIs.
* '''Integration''': Interaktion mit externen Systemen.


----
----


== 2. Implementierungsschritte ==
== 2. Theoretische Grundlagen: DIP, IoC und DI ==
Um eine View Component zu implementieren, folgen Sie im Allgemeinen diesen drei Schritten:
# Erstellen einer View Component Klasse: Leiten Sie von <code>ViewComponent</code> ab.
# Erstellen einer View: Erstellen Sie eine Razor-View-Datei (<code>.cshtml</code>).
# Aufruf in Ihrer View: Verwenden Sie die Helper-Methode oder den Tag Helper.


=== Schritt 1: Die View Component Klasse ===
Um Dependency Injection zu verstehen, müssen wir drei grundlegende Prinzipien betrachten:
Erstellen Sie eine Klasse, die von <code>ViewComponent</code> erbt. Sie sollte normalerweise in einem Ordner <code>ViewComponents</code> platziert werden. Die Klasse muss eine <code>Invoke</code> oder <code>InvokeAsync</code> Methode implementieren.


'''Best Practice''': Benennen Sie die Klasse mit dem Suffix <code>ViewComponent</code> (z. B. <code>GridViewComponent</code>).
=== Dependency Inversion Principle (DIP) ===
DIP besagt, dass High-Level-Module nicht von Low-Level-Modulen abhängen sollten. Beide sollten von '''Abstraktionen''' (Interfaces) abhängen.
* '''Ziel''': Lose Kopplung, Flexibilität.
 
''Beispiel (Lichtschalter-Analogie):''
* ''Ohne DIP'': Ein Lichtschalter ist fest mit einer speziellen Glühbirne verdrahtet. Wenn man die Birne wechseln will, muss man den Schalter ändern.
* ''Mit DIP'': Es gibt eine Steckdose (Interface). Der Schalter funktioniert mit allem, was in die Steckdose passt (Glühbirne, Ventilator).
 
=== Inversion of Control (IoC) ===
IoC bedeutet, die Kontrolle über die Objekterstellung und -verwaltung von der Anwendung an ein Framework oder einen Container abzugeben.
* '''Motto''': "Don't call us, we will call you."
 
=== Dependency Injection (DI) ===
DI ist ein Entwurfsmuster und eine konkrete Umsetzung von IoC. Abhängigkeiten werden einer Klasse von außen (meist durch einen DI-Container) zur Verfügung gestellt ("injiziert"), anstatt dass die Klasse sie selbst erstellt.
 
----
 
== 3. Service-Lebenszyklen (Lifetimes) ==
 
In ASP.NET Core definieren Sie bei der Registrierung eines Services dessen Lebensdauer. Es gibt drei Hauptoptionen:
 
=== 1. Transient (Flüchtig) ===
* '''Erstellung''': Jedes Mal neu, wenn der Service angefordert wird.
* '''Nutzung''': Für leichte, zustandslose Services.
* '''Registrierung''': <code>builder.Services.AddTransient&lt;IMyService, MyService&gt;();</code>
 
=== 2. Scoped (Bereichsbezogen) ===
* '''Erstellung''': Einmal pro Request (z.B. HTTP-Anfrage).
* '''Nutzung''': Der Standard für Web-Anwendungen (z.B. Datenbank-Kontexte, User-Daten). Alle Komponenten innerhalb eines Requests teilen sich dieselbe Instanz.
* '''Registrierung''': <code>builder.Services.AddScoped&lt;IMyService, MyService&gt;();</code>
 
=== 3. Singleton (Einzelstück) ===
* '''Erstellung''': Einmalig für die gesamte Laufzeit der Anwendung (beim ersten Abruf).
* '''Nutzung''': Für globale Zustände, Caches oder Konfigurationen.
* '''Registrierung''': <code>builder.Services.AddSingleton&lt;IMyService, MyService&gt;();</code>
 
----
 
== 4. Implementierung in ASP.NET Core ==
 
Hier sehen wir uns an, wie man Services definiert, registriert und injiziert.
 
=== Schritt 1: Interface und Implementierung definieren ===


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
// GridViewComponent.cs
// ServiceContracts (Interface)
using Microsoft.AspNetCore.Mvc;
namespace ServiceContracts
using System.Threading.Tasks;
{
using System.Collections.Generic;
    public interface ICitiesService
    {
        List<string> GetCities();
    }
}


public class GridViewComponent : ViewComponent
// Services (Implementierung)
namespace Services
{
{
     public async Task<IViewComponentResult> InvokeAsync()
     public class CitiesService : ICitiesService
     {
     {
         // Daten kommen normalerweise aus einer Datenbank oder einem Service
         private List<string> _cities;
         PersonGridModel model = new PersonGridModel()
 
         public CitiesService()
         {
         {
             GridTitle = "Personenliste",
             _cities = new List<string>() { "London", "Paris", "New York", "Tokyo", "Rome" };
            Persons = new List<Person>() {
         }
                new Person() { PersonName = "John", JobTitle = "Manager" },
 
                // ... mehr Daten
         public List<string> GetCities()
            }
         {
         };
            return _cities;
         // Gibt die View zurück (sucht nach Default.cshtml oder dem angegebenen View-Namen)
        }
         return View("Sample", model);  
     }
     }
}
}
</syntaxhighlight>
</syntaxhighlight>


=== Schritt 2: Die View ===
=== Schritt 2: Registrierung im DI-Container (Program.cs) ===
Erstellen Sie eine Razor-View-Datei. Der Suchpfad für die View ist:
<code>Views/Shared/Components/{ViewComponent Name}/{View Name}.cshtml</code>


Für das obige Beispiel würde sich die Datei hier befinden:
<syntaxhighlight lang="csharp">
<code>Views/Shared/Components/Grid/Sample.cshtml</code>
var builder = WebApplication.CreateBuilder(args);
 
=== Schritt 3: Aufrufen der View Component ===
Sie können die Komponente in jeder Razor-View (z. B. <code>Index.cshtml</code>) mit <code>Component.InvokeAsync</code> oder einem Tag Helper aufrufen.


<syntaxhighlight lang="html">
// Registrierung des Services als Transient (Beispiel)
<!-- Standard-Syntax (Bevorzugt) -->
builder.Services.AddTransient<ICitiesService, CitiesService>();
@await Component.InvokeAsync("Grid")


<!-- Tag Helper Syntax -->
// Weitere Dienste...
<vc:grid></vc:grid>
builder.Services.AddControllersWithViews();
</syntaxhighlight>
</syntaxhighlight>


----
=== Schritt 3: Injektion im Controller (Constructor Injection) ===
 
== 3. Stark typisierte View Components ==
Genau wie Standard-Views sollten View Components stark typisierte Modelle für Typsicherheit, IntelliSense und Wartbarkeit verwenden.


=== Das View Model ===
Das ist die empfohlene Methode. Der DI-Container löst die Abhängigkeit automatisch auf.
Definieren Sie eine Klasse, um die Daten zu halten:


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
public class PersonGridModel
public class HomeController : Controller
{
{
     public string GridTitle { get; set; }
    private readonly ICitiesService _citiesService;
     public List<Person> Persons { get; set; }
 
    // Der Service wird über den Konstruktor injiziert
     public HomeController(ICitiesService citiesService)
    {
        _citiesService = citiesService;
    }
 
    [Route("/")]
     public IActionResult Index()
    {
        // Verwendung des Services
        List<string> cities = _citiesService.GetCities();
        return View(cities);
    }
}
}
</syntaxhighlight>
</syntaxhighlight>


=== Die Component View (<code>Sample.cshtml</code>) ===
----
Verwenden Sie die <code>@model</code> Direktive, um die View an die Klasse zu binden.


<syntaxhighlight lang="html">
== 5. Arten der Dependency Injection ==
@model PersonGridModel


<div class="box">
ASP.NET Core unterstützt verschiedene Arten der Injektion:
    <h3>@Model.GridTitle</h3>
 
    <table class="table w-100">
# '''Constructor Injection''' (Empfohlen):
        <thead>
#* Abhängigkeiten werden über den Konstruktor übergeben.
            <tr>
#* Stellt sicher, dass die Klasse validiert instanziiert wird.
                <th>Lfd. Nr.</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (Person person in Model.Persons)
            {
                <tr>
                    <td>@person.PersonName</td>
                    <td>@person.JobTitle</td>
                </tr>
            }
        </tbody>
    </table>
</div>
</syntaxhighlight>


----
# '''Property Injection''':
#* Nutzung des <code>[FromServices]</code> Attributs an Properties.
#* Sinnvoll für optionale Abhängigkeiten (weniger gebräuchlich).


== 4. Parameter übergeben ==
# '''Method Injection''':
Sie können Parameter an <code>InvokeAsync</code> übergeben, um die Ausgabe anzupassen.
#* Übergabe als Parameter an eine Methode.


'''View Component Klasse:'''
# '''Action Method Injection''':
Aktualisieren Sie <code>InvokeAsync</code>, um Argumente zu akzeptieren.
#* Direkt in der Controller-Action mit <code>[FromServices]</code>.
#* Nützlich, wenn der Service nur in einer einzigen Action benötigt wird.


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
public class GridViewComponent : ViewComponent
public IActionResult Index([FromServices] IUserService userService)
{
{
     public async Task<IViewComponentResult> InvokeAsync(PersonGridModel grid) 
     // ...
    {
        return View("Sample", grid);
    }
}
}
</syntaxhighlight>
</syntaxhighlight>


'''Aufruf mit Parametern:'''
----
Übergeben Sie ein anonymes Objekt, bei dem die Eigenschaftsnamen mit den Parameternamen übereinstimmen.


<syntaxhighlight lang="html">
== 6. Best Practices ==
@{
    PersonGridModel myData = new PersonGridModel() { /* ... init ... */ };
}
@await Component.InvokeAsync("Grid", new { grid = myData })
</syntaxhighlight>


'''Tag Helper Syntax:'''
* '''Interfaces nutzen''': Abhängigkeiten sollten immer auf Interfaces basieren, nicht auf konkreten Klassen.
<syntaxhighlight lang="html">
* '''Constructor Injection bevorzugen''': Es ist die sauberste Form der DI.
<vc:grid grid="myData"></vc:grid>  
* '''Service Locator vermeiden''': Rufen Sie nicht manuell <code>GetService()</code> auf (außer in speziellen Factory-Szenarien).
</syntaxhighlight>
* '''Lebenszyklen beachten''': Vermeiden Sie '''Captive Dependencies''' (z.B. einen Scoped Service in einen Singleton injizieren – das führt zu Fehlern).
* '''Kein globaler State''': Vermeiden Sie statische Klassen für User-Daten; nutzen Sie stattdessen Scoped Services oder <code>HttpContext.Items</code>.


----
----


== 5. Rückgabe aus Controllern (ViewComponentResult) ==
== 7. Autofac (Alternative) ==
Sie können eine View Component direkt aus einer Controller-Action zurückgeben. Dies ist nützlich für API-ähnliche Endpunkte, die HTML-Fragmente zurückgeben (z. B. für AJAX-Updates).
 
Obwohl ASP.NET Core einen eingebauten Container hat, bietet '''Autofac''' erweiterte Funktionen (z.B. Property Injection, Decorators, erweiterte Scopes).
 
=== Integration von Autofac ===
 
# NuGet-Paket <code>Autofac.Extensions.DependencyInjection</code> installieren.
# In <code>Program.cs</code> konfigurieren:


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">
[Route("friends-list")]
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
public IActionResult LoadFriendsList()
 
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
{
     PersonGridModel personGridModel = new PersonGridModel()
     // Registrierung mit Autofac-Syntax
    {
    containerBuilder.RegisterType<CitiesService>()
         GridTitle = "Freunde",
         .As<ICitiesService>()
        Persons = new List<Person>() { /* ... */ }
        .InstancePerLifetimeScope(); // Entspricht Scoped
    };
});
    // Gibt das View Component Result zurück
    return ViewComponent("Grid", new { grid = personGridModel });
}
</syntaxhighlight>
</syntaxhighlight>
=== Mapping der Lebenszyklen ===
* <code>InstancePerDependency()</code> = Transient
* <code>InstancePerLifetimeScope()</code> = Scoped
* <code>SingleInstance()</code> = Singleton


----
----


== 6. Best Practices ==
== Zusammenfassung ==
* '''Benennung''': Klassennamen sollten mit <code>ViewComponent</code> enden.
* '''Speicherort''': Detaillierte Ordnerstruktur (<code>Views/Shared/Components/...</code>).
* '''Asynchron''': Verwenden Sie <code>InvokeAsync</code>, um blockierende Threads zu vermeiden.
* '''Einfachheit''': Halten Sie Geschäftslogik aus der Komponente heraus; delegieren Sie an Services.
* '''Typsicherheit''': Bevorzugen Sie immer stark typisierte Modelle gegenüber <code>ViewBag</code> oder <code>ViewData</code>.


== 7. Dinge, die man vermeiden sollte ==
DI ist ein mächtiges Werkzeug, um lose gekoppelte, testbare und wartbare Software zu schreiben. Durch das Verständnis der Prinzipien (DIP, IoC) und der korrekten Anwendung der Lebenszyklen (Transient, Scoped, Singleton) können Sie robuste ASP.NET Core Anwendungen entwickeln.
* '''Übermäßiger Gebrauch''': Verwenden Sie View Components nicht für einfache UI-Teile, die eine Partial View handhaben könnte.
* '''Starke Kopplung''': Koppeln Sie Komponenten nicht an spezifische Controller.
* '''Direkter Datenbankzugriff''': Verwenden Sie stattdessen Dependency Injection und Services.


----
----
''Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).''
''Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).''

Aktuelle Version vom 18. Februar 2026, 21:27 Uhr

Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).



1. Einführung: Was sind Services?

In ASP.NET Core MVC sind Services Klassen, die für die Implementierung der Kern-Geschäftslogik Ihrer Anwendung verantwortlich sind. Sie sind darauf ausgelegt, wiederverwendbar, eigenständig und unabhängig von spezifischen Controllern oder Views zu sein.

Hauptaufgaben von Services

  • Kapselung der Geschäftslogik: Trennung komplexer Operationen von der Präsentationsschicht (Controller/Views).
  • Wiederverwendbarkeit: Ein Service kann von mehreren Controllern genutzt werden (DRY-Prinzip).
  • Testbarkeit: Services können leicht isoliert getestet werden (Unit Tests).
  • Datenzugriff: Kommunikation mit Datenbanken oder APIs.
  • Integration: Interaktion mit externen Systemen.

2. Theoretische Grundlagen: DIP, IoC und DI

Um Dependency Injection zu verstehen, müssen wir drei grundlegende Prinzipien betrachten:

Dependency Inversion Principle (DIP)

DIP besagt, dass High-Level-Module nicht von Low-Level-Modulen abhängen sollten. Beide sollten von Abstraktionen (Interfaces) abhängen.

  • Ziel: Lose Kopplung, Flexibilität.

Beispiel (Lichtschalter-Analogie):

  • Ohne DIP: Ein Lichtschalter ist fest mit einer speziellen Glühbirne verdrahtet. Wenn man die Birne wechseln will, muss man den Schalter ändern.
  • Mit DIP: Es gibt eine Steckdose (Interface). Der Schalter funktioniert mit allem, was in die Steckdose passt (Glühbirne, Ventilator).

Inversion of Control (IoC)

IoC bedeutet, die Kontrolle über die Objekterstellung und -verwaltung von der Anwendung an ein Framework oder einen Container abzugeben.

  • Motto: "Don't call us, we will call you."

Dependency Injection (DI)

DI ist ein Entwurfsmuster und eine konkrete Umsetzung von IoC. Abhängigkeiten werden einer Klasse von außen (meist durch einen DI-Container) zur Verfügung gestellt ("injiziert"), anstatt dass die Klasse sie selbst erstellt.


3. Service-Lebenszyklen (Lifetimes)

In ASP.NET Core definieren Sie bei der Registrierung eines Services dessen Lebensdauer. Es gibt drei Hauptoptionen:

1. Transient (Flüchtig)

  • Erstellung: Jedes Mal neu, wenn der Service angefordert wird.
  • Nutzung: Für leichte, zustandslose Services.
  • Registrierung: builder.Services.AddTransient<IMyService, MyService>();

2. Scoped (Bereichsbezogen)

  • Erstellung: Einmal pro Request (z.B. HTTP-Anfrage).
  • Nutzung: Der Standard für Web-Anwendungen (z.B. Datenbank-Kontexte, User-Daten). Alle Komponenten innerhalb eines Requests teilen sich dieselbe Instanz.
  • Registrierung: builder.Services.AddScoped<IMyService, MyService>();

3. Singleton (Einzelstück)

  • Erstellung: Einmalig für die gesamte Laufzeit der Anwendung (beim ersten Abruf).
  • Nutzung: Für globale Zustände, Caches oder Konfigurationen.
  • Registrierung: builder.Services.AddSingleton<IMyService, MyService>();

4. Implementierung in ASP.NET Core

Hier sehen wir uns an, wie man Services definiert, registriert und injiziert.

Schritt 1: Interface und Implementierung definieren

// ServiceContracts (Interface)
namespace ServiceContracts
{
    public interface ICitiesService
    {
        List<string> GetCities();
    }
}

// Services (Implementierung)
namespace Services
{
    public class CitiesService : ICitiesService
    {
        private List<string> _cities;

        public CitiesService()
        {
            _cities = new List<string>() { "London", "Paris", "New York", "Tokyo", "Rome" };
        }

        public List<string> GetCities()
        {
            return _cities;
        }
    }
}

Schritt 2: Registrierung im DI-Container (Program.cs)

var builder = WebApplication.CreateBuilder(args);

// Registrierung des Services als Transient (Beispiel)
builder.Services.AddTransient<ICitiesService, CitiesService>();

// Weitere Dienste...
builder.Services.AddControllersWithViews();

Schritt 3: Injektion im Controller (Constructor Injection)

Das ist die empfohlene Methode. Der DI-Container löst die Abhängigkeit automatisch auf.

public class HomeController : Controller
{
    private readonly ICitiesService _citiesService;

    // Der Service wird über den Konstruktor injiziert
    public HomeController(ICitiesService citiesService)
    {
        _citiesService = citiesService;
    }

    [Route("/")]
    public IActionResult Index()
    {
        // Verwendung des Services
        List<string> cities = _citiesService.GetCities();
        return View(cities);
    }
}

5. Arten der Dependency Injection

ASP.NET Core unterstützt verschiedene Arten der Injektion:

  1. Constructor Injection (Empfohlen):
    • Abhängigkeiten werden über den Konstruktor übergeben.
    • Stellt sicher, dass die Klasse validiert instanziiert wird.
  1. Property Injection:
    • Nutzung des [FromServices] Attributs an Properties.
    • Sinnvoll für optionale Abhängigkeiten (weniger gebräuchlich).
  1. Method Injection:
    • Übergabe als Parameter an eine Methode.
  1. Action Method Injection:
    • Direkt in der Controller-Action mit [FromServices].
    • Nützlich, wenn der Service nur in einer einzigen Action benötigt wird.
public IActionResult Index([FromServices] IUserService userService)
{
    // ...
}

6. Best Practices

  • Interfaces nutzen: Abhängigkeiten sollten immer auf Interfaces basieren, nicht auf konkreten Klassen.
  • Constructor Injection bevorzugen: Es ist die sauberste Form der DI.
  • Service Locator vermeiden: Rufen Sie nicht manuell GetService() auf (außer in speziellen Factory-Szenarien).
  • Lebenszyklen beachten: Vermeiden Sie Captive Dependencies (z.B. einen Scoped Service in einen Singleton injizieren – das führt zu Fehlern).
  • Kein globaler State: Vermeiden Sie statische Klassen für User-Daten; nutzen Sie stattdessen Scoped Services oder HttpContext.Items.

7. Autofac (Alternative)

Obwohl ASP.NET Core einen eingebauten Container hat, bietet Autofac erweiterte Funktionen (z.B. Property Injection, Decorators, erweiterte Scopes).

Integration von Autofac

  1. NuGet-Paket Autofac.Extensions.DependencyInjection installieren.
  2. In Program.cs konfigurieren:
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
    // Registrierung mit Autofac-Syntax
    containerBuilder.RegisterType<CitiesService>()
        .As<ICitiesService>()
        .InstancePerLifetimeScope(); // Entspricht Scoped
});

Mapping der Lebenszyklen

  • InstancePerDependency() = Transient
  • InstancePerLifetimeScope() = Scoped
  • SingleInstance() = Singleton

Zusammenfassung

DI ist ein mächtiges Werkzeug, um lose gekoppelte, testbare und wartbare Software zu schreiben. Durch das Verständnis der Prinzipien (DIP, IoC) und der korrekten Anwendung der Lebenszyklen (Transient, Scoped, Singleton) können Sie robuste ASP.NET Core Anwendungen entwickeln.


Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).