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.