Architekturüberblick
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-IconGemeinsame Build-Konfiguration
Die Projektdateien bleiben schlank, weil die gemeinsamen Einstellungen in .props-Dateien im Wurzelverzeichnis liegen und über <Import Project="..\Shared.props" /> eingebunden werden:
| Datei | Inhalt |
|---|---|
Shared.props | Zielframeworks, Sprachversion, Nullable; bindet die drei folgenden ein |
Version.props | Paketversion, Aspire-Version, frameworkabhängige Abhängigkeitsversionen |
Package.props | NuGet-Metadaten, Icon und die Regel, dass jedes Paket sein eigenes README ausliefert |
Output.props | Ausgabepfade 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 eingechecktCodeGenSample 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.