Commit-Referenz: 5c37e68
Dokumentations-Stand: Dezember 2025
MbSoftLab.TemplateEngine.Core ist eine .NET 8.0 Bibliothek, die zwei verschiedene Template-Engine-Implementierungen bereitstellt:
- TemplateEngine - Einfacher, schneller String-basierter Template-Engine
- RazorTemplateEngine - Komplexer Razor-basierter Template-Engine für HTML (bereitgestellt durch das optionale Paket
MbSoftLab.TemplateEngine.Core.Razor)
Beide implementieren das gemeinsame ITemplateEngine<T> Interface.
graph TB
subgraph "Client Code"
A[Benutzer-Anwendung]
end
subgraph "MbSoftLab.TemplateEngine.Core"
B[ITemplateEngine<T>]
C[TemplateEngine<T>]
D[[RazorTemplateEngine<T>]]
E[TemplateDataModelProcessor]
F[PlaceholderValueReplacer]
G[ReplacementActionCollection]
H[ITemplateEngineConfig<T>]
I[TemplateEngineConfig<T>]
J[TemplateEngineExtensions]
end
subgraph "MbSoftLab.TemplateEngine.Core.Razor (optional)"
D
K[RazorEngineCore]
end
A --> B
B --> C
B --> D
C --> E
C --> H
D --> H
D --> K
E --> F
F --> G
H --> I
A --> J
J --> B
classDiagram
class ITemplateEngine~T~ {
<<interface>>
+string OpeningDelimiter
+string CloseingDelimiter
+string NullStringValue
+T TemplateDataModel
+string TemplateString
+CultureInfo CultureInfo
+ITemplateEngineConfig~T~ Config
+CreateStringFromTemplate() string
+CreateStringFromTemplate(T) string
+CreateStringFromTemplate(T, string) string
}
class TemplateEngine~T~ {
-string _outputString
-string _openingDelimiter
-string _closeingDelimiter
-T _templateDataModel
-string _templateString
-string _nullStringValue
+CreateStringFromTemplate() string
}
class RazorTemplateEngine~T~ {
-IRazorEngine razorEngine
+CreateStringFromTemplate() string
}
class ITemplateEngineConfig~T~ {
<<interface>>
+string OpeningDelimiter
+string CloseingDelimiter
+string TemplateString
+T TemplateDataModel
+string NullStringValue
+CultureInfo CultureInfo
}
class TemplateEngineConfig~T~ {
-string _openingDelimiter
-string _closeingDelimiter
-string _templateString
-T _templateDataModel
-string _nullStringValue
}
class TemplateDataModel~T~ {
+T Model
+GetNullstringValue() string
}
ITemplateEngine~T~ <|.. TemplateEngine~T~
ITemplateEngine~T~ <|.. RazorTemplateEngine~T~
ITemplateEngineConfig~T~ <|.. TemplateEngineConfig~T~
%% Core ist von Razor entkoppelt; kein RazorEngineTemplateBase
TemplateEngine~T~ --> ITemplateEngineConfig~T~
RazorTemplateEngine~T~ --> ITemplateEngineConfig~T~
RazorTemplateEngine~T~ --> TemplateDataModel~T~
sequenceDiagram
participant Client
participant TemplateEngine
participant Processor as TemplateDataModelProcessor
participant Replacer as PlaceholderValueReplacer
participant Actions as ReplacementActionCollection
Client->>TemplateEngine: CreateStringFromTemplate()
TemplateEngine->>TemplateEngine: Validiere Eingaben
TemplateEngine->>Replacer: new PlaceholderValueReplacer(template, nullValue)
TemplateEngine->>Processor: new TemplateDataModelProcessor(delimiters, replacer)
TemplateEngine->>Processor: ProcessTemplateDataModell(dataModel)
Processor->>Processor: ProcessTemplateDataModelClassMethods()
Processor->>Processor: Iteriere über Methoden
loop Für jede öffentliche parameterlose Methode
Processor->>Processor: Rufe Methode auf
Processor->>Replacer: ReplacePlaceholderWithValue(type, name, value)
Replacer->>Actions: InvokeReplacementActionForType(type, name, value)
Actions->>Replacer: Führe Ersetzung aus
end
Processor->>Processor: ProcessTemplateDataModelClassPropertys()
loop Für jede lesbare Property
Processor->>Processor: Lese Property-Wert
Processor->>Replacer: ReplacePlaceholderWithValue(type, name, value)
Replacer->>Actions: InvokeReplacementActionForType(type, name, value)
Actions->>Replacer: Führe Ersetzung aus
end
Processor-->>TemplateEngine: Verarbeitung abgeschlossen
TemplateEngine->>Replacer: Hole OutputString
Replacer-->>TemplateEngine: Ausgabe-String
TemplateEngine-->>Client: Fertiger String
sequenceDiagram
participant Client
participant RazorEngine as RazorTemplateEngine
participant RazorCore as RazorEngineCore
participant Template as Compiled Template
Client->>RazorEngine: CreateStringFromTemplate()
RazorEngine->>RazorEngine: Validiere Eingaben
RazorEngine->>RazorCore: Compile(templateString)
RazorCore->>RazorCore: Parse Razor-Syntax
RazorCore->>RazorCore: Kompiliere zu C#-Code
RazorCore-->>RazorEngine: IRazorEngineCompiledTemplate
RazorEngine->>Template: Run(templateDataModel)
Template->>Template: Führe kompilierten Code aus
Template->>Template: Zugriff auf Model-Properties
Template-->>RazorEngine: Ausgabe-String
RazorEngine-->>Client: Fertiger String
- Zweck: Schnelle, einfache String-Template-Verarbeitung
- Strategie: Reflection-basierte Platzhalter-Ersetzung
- Performance: Sehr gut für einfache Templates
- Einschränkungen: Keine Collections, keine komplexe Logik
- Zweck: Komplexe HTML-Template-Generierung
- Strategie: Razor-Syntax-Kompilierung
- Performance: Gut für komplexe Templates (Kompilierung beim ersten Mal)
- Vorteile: Volle C#-Syntax, Schleifen, Bedingungen, etc.
- Verantwortung: Verarbeitet TemplateDataModel-Klassen
- Funktionen:
- Extrahiert Properties via Reflection
- Extrahiert parameterlose öffentliche Methoden
- Filtert Basis-Klassen-Methoden (Blacklist)
- Delegiert Wert-Ersetzung an PlaceholderValueReplacer
- Verantwortung: Ersetzt Platzhalter durch Werte
- Funktionen:
- Verwaltet Output-String
- Delegiert typ-spezifische Ersetzung an ReplacementActionCollection
- Handhabt NULL-Werte
- Wendet CultureInfo für Formatierung an
- Verantwortung: Typ-spezifische Ersetzungslogik
- Funktionen:
- Registriert Actions für jeden unterstützten Typ
- Wirft NotSupportedException für nicht unterstützte Typen
- Ermöglicht Erweiterung durch neue Typen
- Zweck: Zentrale Konfiguration für Template-Engines
- Einstellungen:
- Delimiter (OpeningDelimiter, CloseingDelimiter)
- NULL-Wert-String
- CultureInfo für Formatierung
- TemplateDataModel und TemplateString
- CreateStringFromTemplateWithJson: JSON-Deserialisierung + Template-Verarbeitung
- LoadTemplateFromFile: Lädt Template-String aus Datei
1. Client erstellt TemplateEngine mit DataModel und Template
2. Client ruft CreateStringFromTemplate() auf
3. TemplateEngine erstellt PlaceholderValueReplacer
4. TemplateEngine erstellt TemplateDataModelProcessor
5. Processor verarbeitet Methoden:
- Findet öffentliche parameterlose Methoden
- Ruft jede Methode auf
- Übergibt Ergebnis an Replacer
6. Processor verarbeitet Properties:
- Iteriert über alle lesbaren Properties
- Liest jeden Wert
- Übergibt an Replacer
7. Replacer ersetzt jeden Platzhalter:
- Prüft Typ
- Ruft passende ReplacementAction auf
- Ersetzt im Output-String
8. TemplateEngine gibt fertigen String zurück
1. Client erstellt RazorTemplateEngine mit DataModel und Razor-Template
2. Client ruft CreateStringFromTemplate() auf
3. RazorTemplateEngine kompiliert Template (falls nicht gecacht)
4. Kompiliertes Template wird mit DataModel ausgeführt
5. Razor-Code greift direkt auf Model-Properties zu
6. Ausgabe-String wird generiert und zurückgegeben
Entscheidung: Bereitstellung von zwei verschiedenen Engines statt nur einer.
Begründung:
- Einfache Templates benötigen keine Razor-Kompilierung (Performance)
- Komplexe Templates profitieren von Razor-Syntax (Flexibilität)
- Gemeinsames Interface ermöglicht austauschbare Nutzung
Trade-off: Mehr Code-Wartung, aber bessere Use-Case-Abdeckung
Entscheidung: Verwendung von Reflection zur Laufzeit für Property-Zugriff.
Begründung:
- Keine Code-Generierung notwendig
- Funktioniert mit allen Typen ohne zusätzliche Konfiguration
- Einfache API
Trade-off: Geringere Performance als kompilierte Zugriffe, aber akzeptabel für Use-Case
Entscheidung: Dictionary mit Actions pro Typ statt generischer Konvertierung.
Begründung:
- Präzise Kontrolle über Formatierung pro Typ
- Erweiterbar für neue Typen
- Klare Fehlermeldungen bei nicht unterstützten Typen
Trade-off: Mehr initialer Code, aber flexibler und wartbarer
Entscheidung: Delimiter werden getrimmt beim Setzen.
Begründung:
- Verhindert Whitespace-Fehler in Templates
- User-freundlicher
- Konsistentes Verhalten
Trade-off: Keine exakte Whitespace-Kontrolle möglich (sehr selten benötigt)
Entscheidung: Blacklist-basierte Filterung von Basis-Methoden.
Begründung:
- Verhindert ungewollte Methoden-Aufrufe (ToString, GetHashCode, etc.)
- Einfach erweiterbar
- Schutz vor unerwünschtem Verhalten
Trade-off: Muss bei neuen Basis-Klassen erweitert werden
Entscheidung: Ausschließlich .NET 8.0, keine Multi-Targeting.
Begründung:
- Modernste .NET-Features verfügbar
- Bessere Performance
- Einfachere Wartung (nur ein Target)
Trade-off: Nicht mit älteren .NET-Versionen kompatibel
- Template-Caching: Kompilierte Razor-Templates cachen für bessere Performance
- Async-Support: Asynchrone Template-Verarbeitung
- Collection-Support in TemplateEngine: Iteration über Listen direkt im Template
- Methoden mit Parametern: Unterstützung für Methoden-Aufrufe mit Argumenten
- Custom Type Formatters: Benutzer-definierte Formatierung für eigene Typen
- Template-Vererbung: Include/Import von Templates
- Partial Templates: Wiederverwendbare Template-Fragmente
Letzte Aktualisierung: Dezember 2025
Commit-Referenz: 5c37e68