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…“
 
imported>Import
Version 189
Zeile 2: Zeile 2:
----
----


== 1. Einführung: Was sind Services? ==


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


----


== 2. Implementierungsschritte ==
-----
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 ===
== 2. Theoretische Grundlagen: DIP, IoC und DI ==
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>).
Um Dependency Injection zu verstehen, müssen wir drei grundlegende Prinzipien betrachten:


<syntaxhighlight lang="csharp">
=== Dependency Inversion Principle (DIP) ===
// GridViewComponent.cs
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Collections.Generic;


public class GridViewComponent : ViewComponent
DIP besagt, dass High-Level-Module nicht von Low-Level-Modulen abhängen sollten. Beide sollten von '''Abstraktionen''' (Interfaces) abhängen.
{
 
    public async Task<IViewComponentResult> InvokeAsync()  
* '''Ziel''': Lose Kopplung, Flexibilität.
    {
 
        // Daten kommen normalerweise aus einer Datenbank oder einem Service
''Beispiel (Lichtschalter-Analogie):''
        PersonGridModel model = new PersonGridModel()
 
        {
* ''Ohne DIP'': Ein Lichtschalter ist fest mit einer speziellen Glühbirne verdrahtet. Wenn man die Birne wechseln will, muss man den Schalter ändern.
            GridTitle = "Personenliste",
* ''Mit DIP'': Es gibt eine Steckdose (Interface). Der Schalter funktioniert mit allem, was in die Steckdose passt (Glühbirne, Ventilator).
            Persons = new List<Person>() {
 
                new Person() { PersonName = "John", JobTitle = "Manager" },
=== Inversion of Control (IoC) ===
                // ... mehr Daten
 
            }
IoC bedeutet, die Kontrolle über die Objekterstellung und -verwaltung von der Anwendung an ein Framework oder einen Container abzugeben.
        };
 
        // Gibt die View zurück (sucht nach Default.cshtml oder dem angegebenen View-Namen)
* '''Motto''': “Don’t call us, we will call you.”
        return View("Sample", model);
 
    }
=== Dependency Injection (DI) ===
}
 
</syntaxhighlight>
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) ===


=== Schritt 2: Die View ===
* '''Erstellung''': Einmal pro Request (z.B. HTTP-Anfrage).
Erstellen Sie eine Razor-View-Datei. Der Suchpfad für die View ist:
* '''Nutzung''': Der Standard für Web-Anwendungen (z.B. Datenbank-Kontexte, User-Daten). Alle Komponenten innerhalb eines Requests teilen sich dieselbe Instanz.
<code>Views/Shared/Components/{ViewComponent Name}/{View Name}.cshtml</code>
* '''Registrierung''': <code>builder.Services.AddScoped&lt;IMyService, MyService&gt;();</code>


Für das obige Beispiel würde sich die Datei hier befinden:
=== 3. Singleton (Einzelstück) ===
<code>Views/Shared/Components/Grid/Sample.cshtml</code>


=== Schritt 3: Aufrufen der View Component ===
* '''Erstellung''': Einmalig für die gesamte Laufzeit der Anwendung (beim ersten Abruf).
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.
* '''Nutzung''': Für globale Zustände, Caches oder Konfigurationen.
* '''Registrierung''': <code>builder.Services.AddSingleton&lt;IMyService, MyService&gt;();</code>


<syntaxhighlight lang="html">
<!-- Standard-Syntax (Bevorzugt) -->
@await Component.InvokeAsync("Grid")


<!-- Tag Helper Syntax -->
-----
<vc:grid></vc:grid>
</syntaxhighlight>


----
== 4. Implementierung in ASP.NET Core ==


== 3. Stark typisierte View Components ==
Hier sehen wir uns an, wie man Services definiert, registriert und injiziert.
Genau wie Standard-Views sollten View Components stark typisierte Modelle für Typsicherheit, IntelliSense und Wartbarkeit verwenden.


=== Das View Model ===
=== Schritt 1: Interface und Implementierung definieren ===
Definieren Sie eine Klasse, um die Daten zu halten:


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">// ServiceContracts (Interface)
public class PersonGridModel
namespace ServiceContracts
{
{
     public string GridTitle { get; set; }
     public interface ICitiesService
    public List<Person> Persons { get; set; }
    {
        List<string> GetCities();
    }
}
}
</syntaxhighlight>


=== Die Component View (<code>Sample.cshtml</code>) ===
// Services (Implementierung)
Verwenden Sie die <code>@model</code> Direktive, um die View an die Klasse zu binden.
namespace Services
{
    public class CitiesService : ICitiesService
    {
        private List<string> _cities;
 
        public CitiesService()
        {
            _cities = new List<string>() { "London", "Paris", "New York", "Tokyo", "Rome" };
        }


<syntaxhighlight lang="html">
        public List<string> GetCities()
@model PersonGridModel
        {
            return _cities;
        }
    }
}</syntaxhighlight>
=== Schritt 2: Registrierung im DI-Container (Program.cs) ===


<div class="box">
<syntaxhighlight lang="csharp">var builder = WebApplication.CreateBuilder(args);
    <h3>@Model.GridTitle</h3>
    <table class="table w-100">
        <thead>
            <tr>
                <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>


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


== 4. Parameter übergeben ==
// Weitere Dienste...
Sie können Parameter an <code>InvokeAsync</code> übergeben, um die Ausgabe anzupassen.
builder.Services.AddControllersWithViews();</syntaxhighlight>
=== Schritt 3: Injektion im Controller (Constructor Injection) ===


'''View Component Klasse:'''
Das ist die empfohlene Methode. Der DI-Container löst die Abhängigkeit automatisch auf.
Aktualisieren Sie <code>InvokeAsync</code>, um Argumente zu akzeptieren.


<syntaxhighlight lang="csharp">
<syntaxhighlight lang="csharp">public class HomeController : Controller
public class GridViewComponent : ViewComponent
{
{
     public async Task<IViewComponentResult> InvokeAsync(PersonGridModel grid)
    private readonly ICitiesService _citiesService;
 
    // Der Service wird über den Konstruktor injiziert
     public HomeController(ICitiesService citiesService)
     {
     {
         return View("Sample", grid);
         _citiesService = citiesService;
     }
     }
}
</syntaxhighlight>


'''Aufruf mit Parametern:'''
    [Route("/")]
Übergeben Sie ein anonymes Objekt, bei dem die Eigenschaftsnamen mit den Parameternamen übereinstimmen.
    public IActionResult Index()
    {
        // Verwendung des Services
        List<string> cities = _citiesService.GetCities();
        return View(cities);
    }
}</syntaxhighlight>
 
-----
 
== 5. Arten der Dependency Injection ==
 
ASP.NET Core unterstützt verschiedene Arten der Injektion:


<syntaxhighlight lang="html">
# '''Constructor Injection''' (Empfohlen):
@{
#* Abhängigkeiten werden über den Konstruktor übergeben.
    PersonGridModel myData = new PersonGridModel() { /* ... init ... */ };
#* Stellt sicher, dass die Klasse validiert instanziiert wird.
}
@await Component.InvokeAsync("Grid", new { grid = myData })
</syntaxhighlight>


'''Tag Helper Syntax:'''
<!-- -->
<syntaxhighlight lang="html">
# '''Property Injection''':
<vc:grid grid="myData"></vc:grid>  
#* Nutzung des <code>[FromServices]</code> Attributs an Properties.
</syntaxhighlight>
#* Sinnvoll für optionale Abhängigkeiten (weniger gebräuchlich).


----
<!-- -->
# '''Method Injection''':
#* Übergabe als Parameter an eine Methode.


== 5. Rückgabe aus Controllern (ViewComponentResult) ==
<!-- -->
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).
# '''Action Method Injection''':
#* 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 IActionResult Index([FromServices] IUserService userService)
[Route("friends-list")]
public IActionResult LoadFriendsList()
{
{
     PersonGridModel personGridModel = new PersonGridModel()
     // ...
    {
}</syntaxhighlight>
        GridTitle = "Freunde",
        Persons = new List<Person>() { /* ... */ }
    };
    // Gibt das View Component Result zurück
    return ViewComponent("Grid", new { grid = personGridModel });
}
</syntaxhighlight>


----
-----


== 6. Best Practices ==
== 6. Best Practices ==
* '''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 ==
* '''Interfaces nutzen''': Abhängigkeiten sollten immer auf Interfaces basieren, nicht auf konkreten Klassen.
* '''Übermäßiger Gebrauch''': Verwenden Sie View Components nicht für einfache UI-Teile, die eine Partial View handhaben könnte.
* '''Constructor Injection bevorzugen''': Es ist die sauberste Form der DI.
* '''Starke Kopplung''': Koppeln Sie Komponenten nicht an spezifische Controller.
* '''Service Locator vermeiden''': Rufen Sie nicht manuell <code>GetService()</code> auf (außer in speziellen Factory-Szenarien).
* '''Direkter Datenbankzugriff''': Verwenden Sie stattdessen Dependency Injection und Services.
* '''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>.
 
 
-----
 
== 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 ===
 
# NuGet-Paket <code>Autofac.Extensions.DependencyInjection</code> installieren.
# In <code>Program.cs</code> konfigurieren:
 
<syntaxhighlight lang="csharp">builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
 
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
    // Registrierung mit Autofac-Syntax
    containerBuilder.RegisterType<CitiesService>()
        .As<ICitiesService>()
        .InstancePerLifetimeScope(); // Entspricht Scoped
});</syntaxhighlight>
=== Mapping der Lebenszyklen ===
 
* <code>InstancePerDependency()</code> = Transient
* <code>InstancePerLifetimeScope()</code> = Scoped
* <code>SingleInstance()</code> = 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).''
''Hinweis: Diese Inhalte wurden mit Unterstützung von Künstlicher Intelligenz erstellt und redaktionell überprüft (Transparenzhinweis gemäß Art. 50 EU AI Act).''

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).