Skip to content

Architekturüberblick

🇬🇧 This page in English

Wie die Pakete zusammenhängen, welche Entwurfsentscheidungen sie prägen und wo im Repository was liegt.

Aufbau der Sammlung

Nextended ist kein Framework, sondern eine Sammlung unabhängiger Bibliotheken mit einer gemeinsamen Basis. Nur Nextended.Core ist verpflichtend — jedes andere Paket können Sie einzeln nehmen oder weglassen.

Nextended.Core ─┬─ Nextended.Cache ─── Nextended.Imaging
                ├─ Nextended.EF ────── Nextended.Web
                ├─ Nextended.Blazor
                ├─ Nextended.UI
                ├─ Nextended.ResponseFilters ─── Nextended.ResponseFilters.AspNetCore
                └─ Nextended.Aspire ─┬─ Nextended.Aspire.Hosting.N8n
                                     ├─ Nextended.Aspire.Hosting.LocalAI
                                     └─ Nextended.Aspire.Hosting.Supabase ─┐

Nextended.Aspire.Hosting.Grafana ──────────────────────────────────────────┘

eigenständig (nur Aspire.Hosting.AppHost):
  Nextended.Aspire.Hosting.WebDataStudio
  Nextended.Aspire.Hosting.AspireUI
  Nextended.Aspire.Hosting.Php

nur zur Buildzeit:
  Nextended.CodeGen  (verwendet die Attribute aus Nextended.Core)

Die vollständige Matrix mit Zielframeworks und Plattformen steht in der Projektübersicht.

Leitgedanken

Keine Fremdabhängigkeiten für Kernaufgaben

Class Mapping, Deep Clone und Reflection-Helfer sind in Nextended.Core selbst implementiert. Wer MapTo<T>() verwendet, zieht keinen Mapper und keine Profilregistrierung mit ein.

Erweiterungsmethoden statt Basisklassen

Die Bibliotheken erweitern die Typen, die Sie schon haben, statt eigene Basisklassen zu verlangen. IQueryable<T>, DbContext, IBrowserFile, IResourceBuilder<T> bleiben Ihre Typen.

Bedingte Formen statt if-Kaskaden

Mehrere Pakete stellen für ihre Bausteine eine bedingte Variante bereit, die bei nicht erfüllter Bedingung unverändert weitergibt: WhereIf, IncludeIf, AsNoTrackingIf in Nextended.EF, WithReferenceIf, WaitForIf, WithExplicitStartIf in Nextended.Aspire. So bleibt eine Kette eine Kette, statt in verzweigte Duplikate zu zerfallen.

Deklarativ statt verstreut

Nextended.ResponseFilters und Nextended.CodeGen folgen demselben Muster: eine deklarative Beschreibung an einer Stelle statt derselben Entscheidung an vielen. Einmal ein ResponseFilter<OrderDto>, statt in jedem Controller Felder zu leeren; einmal [AutoGenerateDto], statt DTOs und Mapping-Code handzuschreiben.

Kostenlos, wenn ungenutzt

Wo eine Pipeline zwischengeschaltet ist, gibt es einen Kurzschluss. Die Response-Filter analysieren den Typgraphen einer Antwort einmal und überspringen den gesamten Durchlauf, wenn kein registrierter Filter greifen kann.

Aufbau des Repositories

Nextended.sln
├─ Nextended.Core/               Basis: Extensions, Typen, Mapping, Facetten
├─ Nextended.Cache/              ausdrucksbasiertes Caching
├─ Nextended.EF/                 EF-Core-Query- und Graph-Erweiterungen
├─ Nextended.Web/                ASP.NET Core und OData
├─ Nextended.ResponseFilters/            Response-Shaping (providerunabhängig)
├─ Nextended.ResponseFilters.AspNetCore/ MVC-Adapter dazu
├─ Nextended.Blazor/             Blazor-Helfer
├─ Nextended.UI/                 WPF / Windows-Desktop
├─ Nextended.Imaging/            Bildverarbeitung (Windows)
├─ Nextended.CodeGen/            Roslyn-Source-Generator
├─ Nextended.Aspire*/            .NET-Aspire-Hosting-Integrationen
├─ Tests/                        Unit-Tests und die ausführbaren Beispielprojekte
├─ docs/                         Dokumentationssite (englisch), docs/de (deutsch)
│  └─ data/packages.json        einzige Quelle der Wahrheit für alle Paketlisten
└─ tools/Update-PackageDocs.ps1  erzeugt Listen, README-Blöcke und das Doku-Icon

Gemeinsame Build-Konfiguration

Die Projektdateien bleiben schlank, weil die gemeinsamen Einstellungen in .props-Dateien im Wurzelverzeichnis liegen und über <Import Project="..\Shared.props" /> eingebunden werden:

DateiInhalt
Shared.propsZielframeworks, Sprachversion, Nullable; bindet die drei folgenden ein
Version.propsPaketversion, Aspire-Version, framework­abhängige Abhängigkeitsversionen
Package.propsNuGet-Metadaten, Icon und die Regel, dass jedes Paket sein eigenes README ausliefert
Output.propsAusgabepfade und NoWarn

Package.props ist erwähnenswert: dort entscheidet eine einzige Regel, dass das projektlokale README.md ins Paket geht und das Root-README nur als Rückfallebene dient. Vorher lieferten neun Pakete stillschweigend das Root-README an nuget.org aus.

Generierte Dokumentationsteile

Paketlisten, README-Kopf- und Fußbereiche sowie das Icon der Doku-Site werden erzeugt, nicht gepflegt. Quelle ist docs/data/packages.json; die Doku-Site liest sie über Liquid direkt, die READMEs über tools/Update-PackageDocs.ps1. Der Generator schlägt fehl, wenn ein Paket in der Datei fehlt oder umgekehrt — die Listen können also nicht mehr auseinanderlaufen.

Testaufbau

Tests/
├─ Nextended.Core.Tests/                        Extensions, Mapping, Typen
├─ Nextended.EF.Tests/                          Query- und Graph-Erweiterungen
├─ Nextended.ResponseFilters.Tests/             Regeln, Prädikate, Strukturänderungen
├─ Nextended.Aspire.Hosting.*.Tests/            Ressourcenaufbau
└─ TestProjects/                                ausführbare Beispiele, keine Tests
   ├─ *.AppHost/                                ein Aspire-AppHost pro Integration
   ├─ Php.WebDemo/                              .NET-Gegenstück zum PHP-Beispiel
   └─ CodeGenSample/                            alle vier Generatoren, Ausgabe eingecheckt

CodeGenSample ist bewusst so gebaut, dass die erzeugten Dateien im Repository liegen. Ein git diff nach dem Build zeigt damit unmittelbar, was eine Konfigurationsänderung bewirkt.