diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6eaa355 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,55 @@ +# Changelog + +Alle wichtigen Änderungen an diesem Projekt werden in dieser Datei dokumentiert. + +Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/), +und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). + +## [Unveröffentlicht] + +### Geändert +- Veröffentlichungsprozess aktualisiert: NuGet-Publish-Aktion durch `dotnet pack` und `dotnet nuget push` ersetzt (Commit: 5c37e68) + +## [1.0.8-preview2] - Stand: Commit 5c37e68 + +### Hinzugefügt +- RazorTemplateEngine für komplexe HTML-Templates mit Razor-Syntax +- Unterstützung für Razor-Templates mit der `RazorTemplateEngine` Klasse +- `ITemplateEngine` Interface für beide Template-Engine-Implementierungen +- `ITemplateEngineConfig` Interface und `TemplateEngineConfig` Klasse für Konfiguration +- Erweiterungsmethoden `CreateStringFromTemplateWithJson` und `LoadTemplateFromFile` +- Demo-Projekt mit Razor-Template-Beispielen +- Unterstützung für parameterlose öffentliche Methoden im TemplateDataModel (Syntax: `${MethodName()}`) + +### Funktionen +- Einfacher String-basierter Template-Engine (`TemplateEngine` und `TemplateEngine`) +- Razor-basierter Template-Engine (`RazorTemplateEngine`) +- Anpassbare Delimiter (Standard: `${` und `}`) +- Konfigurierbare NULL-Wert-Behandlung (Standard: "NULL") +- Kultur-spezifische Formatierung für Datum und Zahlen (Standard: en-US) +- JSON-Deserialisierung für TemplateDataModel +- Laden von Templates aus Dateien + +### Unterstützte Datentypen +- Primitive Typen: String, Byte, Short, UShort, Long, ULong, SByte, Char +- Numerische Typen: Int16, Int32, Int64, UInt16, UInt32, UInt64, Decimal, Double +- Weitere Typen: DateTime, Boolean + +### Technische Details +- Target Framework: .NET 8.0 +- Assembly Version: 1.0.8.2 +- Package Version: 1.0.8-preview2 +- Abhängigkeit: RazorEngineCore 2020.10.1 + +### Build und CI/CD +- GitHub Actions Workflows für Build (Develop und Master Branch) +- GitHub Actions Workflow für Release und NuGet-Veröffentlichung +- Automatische NuGet-Package-Generierung beim Build + +--- + +## Versions-Historie (Zusammenfassung) + +Die Version 1.0.8-preview2 ist die aktuelle Entwicklungsversion mit Razor-Template-Unterstützung. + +**Commit-Referenz für diese Dokumentation:** 5c37e68 (Basis-Commit für Dokumentation) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f13e941 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 MbSoftLab + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 3f72cfe..7224d65 100644 --- a/README.md +++ b/README.md @@ -1,218 +1,222 @@ -# MbSoftLab.TemplateEngine.Core +# MbSoftLab.TemplateEngine.Core -![BuildFromDevelop](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/workflows/BuildFromDevelop/badge.svg?branch=develop) ![BuildFromMaster](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/workflows/BuildFromMaster/badge.svg?branch=master)![Release](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/workflows/Release/badge.svg) - -*Codequality (master branch)* +[![Build (develop)](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/workflows/BuildFromDevelop/badge.svg?branch=develop)](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/actions) +[![Build (master)](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/workflows/BuildFromMaster/badge.svg?branch=master)](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/actions) +[![Release](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/workflows/Release/badge.svg)](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/actions) [![CodeFactor](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core/badge)](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core) +[![NuGet](https://img.shields.io/nuget/v/MbSoftLab.TemplateEngine.Core.svg)](https://www.nuget.org/packages/MbSoftLab.TemplateEngine.Core/) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) -*Codequality (develop branch)* -[![CodeFactor](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core/badge/develop)](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core/overview/develop) -```csharp -namespace MbSoftLab.TemplateEngine.Core -{ - public class TemplateEngine : TemplateEngine{} +> Eine leistungsstarke und flexible Template-Engine für .NET 8.0 mit Unterstützung für einfache String-Templates und komplexe Razor-Templates. - public class TemplateEngine{...} -} -``` - - -The TemplateEngine replaces values from properties of C# classes in template strings. -The C# class with the data holding properties is called the TemplateDataModel class. -The string with the placeholders is called a string template or template string. +--- +## 🚀 Schnellstart -You can bind the value from your C-property to your string template by using `${YourPropertyName}`. -You can set a custom delimiters. Use the `OpeningDelimiter` and `CloseingDelimiter` properties to handle this. +### Installation -Also you can access parameterless public methods of TemplateDataModell classes by using `${MethodName()}` in your template. +```bash +dotnet add package MbSoftLab.TemplateEngine.Core +``` + +### Einfaches Beispiel +```csharp +using MbSoftLab.TemplateEngine.Core; -The default is `${` for the start delimiter and `}` for the end delimiter. +var person = new { FirstName = "Max", LastName = "Mustermann" }; +var engine = new TemplateEngine(person, "Hallo ${FirstName} ${LastName}!"); +string result = engine.CreateStringFromTemplate(); +// Output: "Hallo Max Mustermann!" +``` +### Razor-Template-Beispiel ```csharp - Person person = new Person - { - FirstName = "Jo", - LastName="Doe" - }; - -string template = "${FirstName}, ${LastName}"; +public class Person : TemplateDataModel +{ + public string FirstName { get; set; } + public List Tags { get; set; } +} -TemplateEngine templateEngine = new TemplateEngine(person,template); -string outputString = templateEngine.CreateStringFromTemplate(); +var person = new Person { + FirstName = "Anna", + Tags = new List { "Developer", "Designer" } +}; + +var engine = new RazorTemplateEngine(); +engine.TemplateString = @" +

@Model.FirstName

+
    +@foreach(var tag in Model.Tags) { +
  • @tag
  • +} +
"; -Console.Write(outputString); // Output: Jo, Doe +string html = engine.CreateStringFromTemplate(person); ``` --- -## Install Package +## ✨ Features -**NuGet Package:** -https://www.nuget.org/packages/MbSoftLab.TemplateEngine.Core/ +### Zwei leistungsstarke Engines -```PM -PM> Install-Package MbSoftLab.TemplateEngine.Core -``` +- **TemplateEngine** - Schnell und einfach für String-basierte Templates + - Property-Platzhalter: `${PropertyName}` + - Methoden-Aufrufe: `${MethodName()}` + - Anpassbare Delimiters + - Kultur-spezifische Formatierung + +- **RazorTemplateEngine** - Flexibel für komplexe HTML-Templates + - Volle Razor-Syntax + - Listen und Collections + - Bedingungen und Schleifen + - Verschachtelte Objekte ---- +### Unterstützte Datentypen -## Methods -|Methodname |Description | -|------------------------------------------------------------------------|-----------------------------------------------------------------| -|`string CreateStringFromTemplate([string template])` |*Creates a String from Datamodell and Template* | -|`string CreateStringFromJson(templateEngine, string jsonData)` |*Loads the Templatedata from JSON*. - | -|`void LoadTemplateFromFile(string filename)` |*Loads a Stringtemplate from file*. | -|`TemplateEngine()` |Constructor | -|`TemplateEngine(object templateDataModel, string stringTemplate)` |Constructor | -|`TemplateEngine(object templateDataModel)` |Constructor | -|`TemplateEngine()` |Constructor | -|`TemplateEngine(T templateDataModel, string stringTemplate)` |Constructor | -|`TemplateEngine(T templateDataModel)` |Constructor | +✅ String, Byte, Short, Int, Long, Decimal, Double, DateTime, Boolean +❌ Collections (nur mit RazorTemplateEngine) --- -## Propertys +## 📚 Dokumentation + +**Vollständige Dokumentation verfügbar unter [`/docs`](/docs):** -|Propertyname |Datatype |Description | -|----------------------------------------|------------------|-------------------------------------------------------------------------| -|`OpeningDelimiter` |String |Set the beginning delimiter for propertyreplacement | -|`CloseingDelimiter` |String |Set the ending delimiter for propertyreplacement | -|`TemplateDataModel` |Generic / object |Modell with Properys for Dataholding | -|`TemplateString` |string |Templatestring | -|`NullStringValue` |string |String for NULL-Values | -|`CultureInfo` |CultureInfo |Culture for Double and DateTime values | +| Dokument | Beschreibung | +|----------|--------------| +| [📖 Übersicht](/docs/README.md) | Dokumentations-Einstieg | +| [🏗️ Architektur](/docs/architecture.md) | System-Design und Komponenten | +| [📋 API-Referenz](/docs/api.md) | Vollständige API-Dokumentation | +| [💡 Beispiele](/docs/examples.md) | 16+ praktische Code-Beispiele | +| [👨‍💻 Entwickler-Leitfaden](/docs/development.md) | Contribution Guidelines | +| [📝 CHANGELOG](/CHANGELOG.md) | Versions-Historie | +| [🎉 Release Notes](/RELEASENOTES.md) | Aktuelle Version 1.0.8-preview2 | --- -## Exampels +## 💡 Verwendungsbeispiele -### **Load the template and fill with Data from modell** -```csharp -// Create a modell Class for Data - TemplateDataModel templateDataModel = new TemplateDataModel - { - ProjectName = "Projektname" - }; +### Template aus Datei laden -string template = "${ProjectName}"; +```csharp +var engine = new TemplateEngine(customer); +engine.LoadTemplateFromFile("email-template.txt"); +string email = engine.CreateStringFromTemplate(); +``` -TemplateEngine templateEngine = new TemplateEngine(templateDataModel,template); -string outputString = templateEngine.CreateStringFromTemplate(); +### JSON-Daten verwenden -Console.Write(outputString); // Output: ProjectName -``` -### **Load template from file** ```csharp - TemplateDataModel templateDataModel = new TemplateDataModel - { - ProjectName = "Projektname", - CustomerId = "1234", - ProjectUrl = "https://google.com" - }; - - TemplateEngine templateEngine = new TemplateEngine(templateDataModel); - templateEngine.LoadTemplateFromFile("Html.template.html"); - string outputString = templateEngine.CreateStringFromTemplate(); - - Console.WriteLine(outputString); +string jsonData = "{\"Name\":\"Lisa\",\"Email\":\"lisa@example.com\"}"; +var engine = new TemplateEngine(); +engine.TemplateString = "Kunde: ${Name}, E-Mail: ${Email}"; +string result = engine.CreateStringFromTemplateWithJson(jsonData); ``` +### Custom Delimiters -### **Template and model over PropertyInjection** ```csharp - TemplateDataModel templateDataModel = new TemplateDataModel - { - ProjectName = "Projectname", - CustomerId = "1234", - ProjectUrl = "https://google.com" - }; - - string template = "

${ProjectName}

"; - TemplateEngine templateEngine = new TemplateEngine(); - templateEngine.TemplateDataModel = templateDataModel; - templateEngine.TemplateString = template; - Console.WriteLine(templateEngine.CreateStringFromTemplate()); - +var engine = new TemplateEngine(person, "[[FirstName]] [[LastName]]"); +engine.OpeningDelimiter = "[["; +engine.CloseingDelimiter = "]]"; ``` -### **Template and model over DependencyInjection** +### NULL-Werte behandeln + ```csharp +var engine = new TemplateEngine(customer, "${Email}"); +engine.NullStringValue = "Keine Angabe"; +``` - TemplateDataModel templateDataModel = new TemplateDataModel - { - ProjectName = "Projectname", - CustomerId = "1234", - ProjectUrl = "https://google.com" - }; +Weitere Beispiele und Tutorials finden Sie in der [Beispiele-Dokumentation](/docs/examples.md). - string template = "

${ProjectName}

"; - TemplateEngine templateEngine = new TemplateEngine(templateDataModel,template); - Console.WriteLine(templateEngine.CreateStringFromTemplate()); +--- +## 🔧 Hauptfunktionen -``` -### **TemplateEngine with PropertyInjection and generic type** -```csharp - TemplateDataModel templateDataModel = new TemplateDataModel - { - ProjectName = "Projectname", - CustomerId = null, - ProjectUrl = "https://google.de" - }; - - string template = "

{{ProjectName}}

{{CustomerId}}

"; - TemplateEngine templateEngine = new TemplateEngine() - { - TemplateDataModel = templateDataModel, - TemplateString = template, - OpeningDelimiter = "{{", - CloseingDelimiter = "}}", - NullStringValue = "???" - }; - Console.WriteLine(templateEngine.CreateStringFromTemplate()); +### TemplateEngine + +| Feature | Beschreibung | +|---------|--------------| +| Property-Binding | `${PropertyName}` für einfache Werte | +| Methoden-Aufrufe | `${MethodName()}` für parameterlose Methoden | +| Custom Delimiters | Anpassbare Start-/End-Zeichen | +| NULL-Behandlung | Konfigurierbarer NULL-String | +| Formatierung | Kultur-spezifisch (CultureInfo) | +| JSON-Support | Direkte Deserialisierung | +| File-Loading | Templates aus Dateien laden | + +### RazorTemplateEngine + +| Feature | Beschreibung | +|---------|--------------| +| Razor-Syntax | Volle C#-Unterstützung in Templates | +| Collections | Listen, Arrays, IEnumerable | +| Kontrollstrukturen | `@if`, `@foreach`, `@for`, `@switch` | +| Verschachtelung | Komplexe Objekthierarchien | +| Type-Safety | Generische Typisierung | +--- + +## 📦 NuGet Package + +```bash +# .NET CLI +dotnet add package MbSoftLab.TemplateEngine.Core + +# Package Manager +Install-Package MbSoftLab.TemplateEngine.Core + +# PackageReference + ``` +**NuGet Gallery:** https://www.nuget.org/packages/MbSoftLab.TemplateEngine.Core/ + +--- + +## 🤝 Contributing + +Wir freuen uns über Beiträge! Bitte lesen Sie unseren [Entwickler-Leitfaden](/docs/development.md) für: + +- Entwicklungsumgebung einrichten +- Code-Konventionen +- Branch-Strategie +- Pull Request Prozess --- - ## Datatype compatibility - -- ✔ String -- ✔ Byte -- ✔ Short -- ✔ UShort -- ✔ Long -- ✔ ULong -- ✔ SByte -- ✔ Char -- ✔ UInt16 -- ✔ Int32 -- ✔ UInt64 -- ✔ Int16 -- ✔ Int32 -- ✔ Int64 -- ✔ Decimal -- ✔ Double -- ✔ DateTime -- ✔ Boolean -- ❌ Object -- ❌ CustomClasses -- ❌ IList, List, Dictionary, IEnumerable, etc.. - - +## 📄 Lizenz + +Dieses Projekt ist unter der [MIT-Lizenz](LICENSE) lizenziert. + +Copyright © 2021 MbSoftLab --- - -## Repo -https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core +## 🔗 Links + +- **GitHub Repository:** https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core +- **Issues/Feedback:** https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/issues +- **NuGet Package:** https://www.nuget.org/packages/MbSoftLab.TemplateEngine.Core/ + --- -## Issues +## 🆕 Version 1.0.8-preview2 + +**Highlights:** +- ✨ RazorTemplateEngine für komplexe HTML-Templates +- ✨ Erweiterte Methoden-Aufrufe in Templates +- 🔧 Verbesserter Build- und Release-Prozess +- 📚 Umfassende deutsche Dokumentation + +Siehe [Release Notes](/RELEASENOTES.md) für Details. + +--- -[report an issue](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/issues) \ No newline at end of file +

+ Built with ❤️ by MbSoftLab +

diff --git a/RELEASENOTES.md b/RELEASENOTES.md new file mode 100644 index 0000000..51a0d0e --- /dev/null +++ b/RELEASENOTES.md @@ -0,0 +1,138 @@ +# Release Notes + +## Version 1.0.8-preview2 + +**Release-Datum:** In Entwicklung +**Commit-Referenz:** 5c37e68 + +### Übersicht + +Diese Preview-Version erweitert die MbSoftLab.TemplateEngine.Core um Razor-Template-Unterstützung und verbessert den Build- und Veröffentlichungsprozess. + +--- + +## ✨ Neue Features + +### 1. Razor Template Engine +Die neue `RazorTemplateEngine` Klasse ermöglicht die Nutzung von Razor-Syntax für komplexe HTML-Templates: + +```csharp +Person person = new Person { FirstName = "Max", LastName = "Mustermann" }; +var engine = new RazorTemplateEngine(); +engine.LoadTemplateFromFile("template.cshtml"); +string result = engine.CreateStringFromTemplate(person); +``` + +**Vorteile:** +- Volle Razor-Syntax-Unterstützung (Schleifen, Bedingungen, etc.) +- Typsichere Template-Erstellung +- Kompilierte Templates für bessere Performance + +### 2. Erweiterte Template-Funktionalität +- **Methodenaufrufe:** Templates können jetzt parameterlose öffentliche Methoden aufrufen: `${MethodName()}` +- **JSON-Unterstützung:** Direkte Deserialisierung von JSON in TemplateDataModel +- **Template aus Datei laden:** `LoadTemplateFromFile()` Erweiterungsmethode + +### 3. Einheitliches Interface-Design +- `ITemplateEngine` als gemeinsames Interface für beide Engine-Typen +- `ITemplateEngineConfig` für konsistente Konfiguration +- Bessere Erweiterbarkeit und Testbarkeit + +--- + +## 🔧 Verbesserungen + +### Build und Deployment +- **Modernisierter Release-Workflow:** + - Umstellung von veralteter NuGet-Publish-Action auf native dotnet-Befehle + - `dotnet pack` für Package-Erstellung + - `dotnet nuget push` für NuGet-Veröffentlichung + - Verbesserte Zuverlässigkeit und Wartbarkeit + +### Code-Qualität +- XML-Dokumentation für alle öffentlichen APIs +- Einheitliche Fehlerbehandlung +- Kultur-spezifische Formatierung konfigurierbar + +--- + +## 📦 Technische Spezifikationen + +### Framework und Versionen +- **Target Framework:** .NET 8.0 +- **Assembly Version:** 1.0.8.2 +- **Package Version:** 1.0.8-preview2 +- **Lizenz:** MIT + +### Abhängigkeiten +- RazorEngineCore 2020.10.1 + +### Build-Konfiguration +- Automatische Package-Generierung beim Build +- XML-Dokumentationsdatei wird generiert +- NuGet-Package mit Logo und vollständigen Metadaten + +--- + +## 🎯 Anwendungsfälle + +### Simple String-Templates +Ideal für einfache Platzhalter-Ersetzungen in Konfigurationsdateien, E-Mails oder Berichten. + +### Komplexe HTML-Templates +Mit der Razor-Engine können Sie komplexe HTML-Dokumente mit Schleifen, Bedingungen und verschachtelten Strukturen erstellen. + +### Code-Generierung +Nutzen Sie die Template-Engines zur automatischen Code-, Konfigurations- oder Dokumentationsgenerierung. + +--- + +## 📝 Migration von früheren Versionen + +Die API ist abwärtskompatibel. Bestehender Code funktioniert weiterhin: + +```csharp +// Alter Code funktioniert weiterhin +var engine = new TemplateEngine(dataModel, template); +string result = engine.CreateStringFromTemplate(); +``` + +Neue Features können optional genutzt werden: + +```csharp +// Neuer Code mit Razor +var razorEngine = new RazorTemplateEngine(dataModel, razorTemplate); +string result = razorEngine.CreateStringFromTemplate(); +``` + +--- + +## 🐛 Bekannte Einschränkungen + +1. **Collections nicht unterstützt** in der einfachen TemplateEngine + - Workaround: Verwenden Sie RazorTemplateEngine für Listen und Arrays + +2. **Nur parameterlose Methoden** werden unterstützt + - Zukünftige Versionen könnten Methoden mit Parametern unterstützen + +3. **XML-Dokumentations-Warnung** bei `LoadTemplateFromFile` + - Wird in der nächsten Version behoben + +--- + +## 🔗 Links und Ressourcen + +- **NuGet Package:** https://www.nuget.org/packages/MbSoftLab.TemplateEngine.Core/ +- **GitHub Repository:** https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core +- **Issues:** https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/issues +- **Dokumentation:** Siehe `/docs` Verzeichnis + +--- + +## 🙏 Danksagung + +Danke an alle Mitwirkenden und Nutzer für ihr Feedback und ihre Unterstützung bei der Weiterentwicklung dieses Projekts. + +--- + +**Commit-Referenz für diese Release Notes:** 5c37e68 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..ed1cd88 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,237 @@ +# MbSoftLab.TemplateEngine.Core - Dokumentation + +**Version:** 1.0.8-preview2 +**Commit-Referenz:** 5c37e68 +**Dokumentations-Stand:** Dezember 2025 + +--- + +## Willkommen + +Willkommen zur offiziellen Dokumentation der **MbSoftLab.TemplateEngine.Core** Bibliothek - einer leistungsstarken und flexiblen Template-Engine für .NET 8.0. + +Diese Bibliothek bietet zwei verschiedene Ansätze zur Template-Verarbeitung: +- **TemplateEngine** - Schnell und einfach für String-basierte Templates +- **RazorTemplateEngine** - Mächtig und flexibel für komplexe HTML-Templates mit Razor-Syntax + +--- + +## 📚 Dokumentations-Struktur + +### [Architektur](architecture.md) +Detaillierte technische Übersicht der Bibliothek: +- Gesamt-Architektur und Komponenten-Diagramme +- Klassen-Hierarchie und Beziehungen +- Datenfluss und Verarbeitungs-Pipelines +- Design-Entscheidungen und Begründungen +- Erweiterungspunkte für zukünftige Features + +**Für wen:** Entwickler, die die interne Struktur verstehen wollen + +### [API-Dokumentation](api.md) +Vollständige API-Referenz: +- Alle öffentlichen Klassen und Interfaces +- Methoden-Signaturen und Parameter +- Eigenschaften und deren Verwendung +- Template-Syntax für beide Engine-Typen +- Unterstützte Datentypen +- Best Practices und Fehlerbehandlung + +**Für wen:** Entwickler, die die API verwenden + +### [Beispiele und Tutorials](examples.md) +Praktische Codebeispiele: +- Schnellstart-Anleitung +- Einfache bis fortgeschrittene Beispiele +- Razor-Template-Beispiele +- Real-World-Szenarien (E-Mail, Reports, Konfigurationen) +- Tipps und Tricks für effiziente Nutzung + +**Für wen:** Einsteiger und Entwickler, die konkrete Anwendungsfälle suchen + +### [Entwickler-Leitfaden](development.md) +Informationen für Contributors: +- Entwicklungsumgebung einrichten +- Projekt-Struktur und Organisation +- Build, Test und Debugging +- Code-Konventionen und Standards +- Contribution Guidelines +- CI/CD Pipeline-Details + +**Für wen:** Contributors und Maintainer + +--- + +## 🚀 Schnellstart + +### Installation + +```bash +# NuGet Package Manager +Install-Package MbSoftLab.TemplateEngine.Core + +# .NET CLI +dotnet add package MbSoftLab.TemplateEngine.Core +``` + +### Erstes Beispiel + +```csharp +using MbSoftLab.TemplateEngine.Core; + +// Datenmodell +var person = new { FirstName = "Max", LastName = "Mustermann" }; + +// Template +string template = "Hallo ${FirstName} ${LastName}!"; + +// Template-Engine +var engine = new TemplateEngine(person, template); + +// String erstellen +string result = engine.CreateStringFromTemplate(); +// Output: "Hallo Max Mustermann!" +``` + +Mehr Beispiele finden Sie in der [Beispiele-Dokumentation](examples.md). + +--- + +## 📖 Wichtige Dokumente + +### [CHANGELOG.md](/CHANGELOG.md) +Komplette Versions-Historie mit allen Änderungen, neuen Features und Bugfixes. + +### [RELEASENOTES.md](/RELEASENOTES.md) +Detaillierte Release-Informationen für die aktuelle Version mit Migration-Guides und bekannten Einschränkungen. + +### [README.md](/README.md) +Projekt-Übersicht mit grundlegenden Informationen und Links. + +--- + +## 🎯 Häufige Anwendungsfälle + +### 1. Einfache String-Templates +Für Platzhalter-Ersetzungen in Konfigurationen, E-Mails oder einfachen Texten. + +```csharp +var engine = new TemplateEngine(customer, "Hallo ${Name}!"); +``` + +→ Siehe [Einfache Beispiele](/docs/examples/#einfache-beispiele) + +### 2. Komplexe HTML-Templates +Für dynamische HTML-Generierung mit Schleifen, Bedingungen und verschachtelten Objekten. + +```csharp +var engine = new RazorTemplateEngine(); +engine.TemplateString = "@foreach(var item in Model.Items) {
  • @item
  • }"; +``` + +→ Siehe [Razor-Templates](/docs/examples/#razor-templates) + +### 3. Report-Generierung +Für automatisierte Berichte aus Datenmodellen. + +→ Siehe [Praxis-Szenarien](/docs/examples/#praxis-szenarien) + +### 4. Code-Generierung +Für Template-basierte Code- oder Konfigurations-Generierung. + +→ Siehe [Entwickler-Leitfaden](/docs/development/) + +--- + +## 💡 Kernkonzepte + +### Template-Engine (String-basiert) +- **Platzhalter:** `${PropertyName}` oder `${MethodName()}` +- **Custom Delimiters:** Konfigurierbar +- **NULL-Behandlung:** Anpassbarer NULL-String +- **Formatierung:** Kultur-abhängig für Zahlen und Datum +- **Performance:** Sehr schnell für einfache Templates + +### RazorTemplateEngine (Razor-basiert) +- **Razor-Syntax:** Volle C#-Unterstützung +- **Schleifen:** `@foreach`, `@for` +- **Bedingungen:** `@if`, `@switch` +- **Collections:** Listen und Arrays unterstützt +- **Kompilierung:** Templates werden kompiliert für bessere Performance + +--- + +## 🔧 Funktions-Übersicht + +### Unterstützte Datentypen (TemplateEngine) +✅ String, Byte, Short, Int, Long, Decimal, Double, DateTime, Boolean +❌ Collections, Custom Classes (→ Nutzen Sie RazorTemplateEngine) + +### Features +- [x] Property-basierte Platzhalter +- [x] Methoden-Aufrufe (parameterlos) +- [x] Custom Delimiters +- [x] NULL-Wert-Konfiguration +- [x] Kultur-spezifische Formatierung +- [x] JSON-Deserialisierung +- [x] Template aus Datei laden +- [x] Razor-Template-Unterstützung +- [x] Generische Type-Safety +- [x] Interface-basiertes Design +- [x] Konfigurations-Objekt + +--- + +## 📊 Versions-Informationen + +### Aktuelle Version: 1.0.8-preview2 + +**Highlights:** +- Razor-Template-Engine für komplexe HTML-Templates +- Erweiterte Methoden-Aufrufe in Templates +- Verbesserter Build- und Release-Prozess +- Umfassende Dokumentation + +**Breaking Changes:** Keine (abwärtskompatibel) + +Siehe [RELEASENOTES.md](/RELEASENOTES.md) für Details. + +--- + +## 🤝 Contribution + +Wir freuen uns über Beiträge! Bitte lesen Sie den [Entwickler-Leitfaden](/docs/development/#contribution-guidelines) für: +- Branch-Strategie +- Commit-Konventionen +- Pull Request Process +- Code-Standards + +--- + +## 📝 Support und Feedback + +### Issues melden +[GitHub Issues](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/issues) + +### Fragen stellen +[GitHub Discussions](https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core/discussions) + +### Code-Qualität prüfen +[![CodeFactor](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core/badge)](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core) + +--- + +## 📦 Links + +- **NuGet Package:** https://www.nuget.org/packages/MbSoftLab.TemplateEngine.Core/ +- **GitHub Repository:** https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core +- **License:** MIT (siehe [LICENSE](/LICENSE)) + +--- + +**Letzte Aktualisierung:** Dezember 2025 +**Commit-Referenz:** 5c37e68 + +--- + +*Diese Dokumentation wurde automatisch generiert und wird kontinuierlich aktualisiert.* diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..e904a39 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,643 @@ +# API-Dokumentation + +**Commit-Referenz:** 5c37e68 +**Dokumentations-Stand:** Dezember 2025 + +--- + +## Inhaltsverzeichnis + +1. [Übersicht](#übersicht) +2. [TemplateEngine](#templateengine) +3. [RazorTemplateEngine](#razortemplateengine) +4. [Interfaces](#interfaces) +5. [Konfiguration](#konfiguration) +6. [Erweiterungsmethoden](#erweiterungsmethoden) +7. [Datentypen](#datentypen) + +--- + +## Übersicht + +Die MbSoftLab.TemplateEngine.Core Bibliothek bietet zwei Hauptklassen für Template-Verarbeitung: + +- **TemplateEngine / TemplateEngine:** Für einfache String-basierte Templates +- **RazorTemplateEngine:** Für komplexe Razor-basierte Templates + +Beide implementieren das `ITemplateEngine` Interface. + +--- + +## TemplateEngine + +### TemplateEngine (nicht-generisch) + +```csharp +public class TemplateEngine : TemplateEngine, ITemplateEngine +``` + +**Beschreibung:** Vereinfachte Version von `TemplateEngine` mit `object` als TemplateDataModel-Typ. + +#### Konstruktoren + +```csharp +// 1. Mit DataModel und Template +public TemplateEngine(object templateDataModel, string stringTemplate) + +// 2. Nur mit DataModel +public TemplateEngine(object templateDataModel) + +// 3. Parameterlos (Eigenschaften später setzen) +public TemplateEngine() +``` + +#### Beispiel + +```csharp +var person = new { FirstName = "Max", LastName = "Mustermann" }; +var engine = new TemplateEngine(person, "Hallo ${FirstName} ${LastName}!"); +string result = engine.CreateStringFromTemplate(); +// Ergebnis: "Hallo Max Mustermann!" +``` + +--- + +### TemplateEngine (generisch) + +```csharp +public class TemplateEngine : ITemplateEngine +``` + +**Beschreibung:** Generische Template-Engine für typisierte DataModels. + +#### Eigenschaften + +| Eigenschaft | Typ | Standardwert | Beschreibung | +|-------------|-----|--------------|--------------| +| `OpeningDelimiter` | `string` | `"${"` | Anfangs-Delimiter für Platzhalter | +| `CloseingDelimiter` | `string` | `"}"` | End-Delimiter für Platzhalter | +| `TemplateDataModel` | `T` | - | Datenmodell mit Properties/Methoden | +| `TemplateString` | `string` | - | Template-String mit Platzhaltern | +| `NullStringValue` | `string` | `"NULL"` | Ersatzwert für NULL-Properties | +| `CultureInfo` | `CultureInfo` | `en-US` | Kultur für Zahlen-/Datumsformatierung | +| `Config` | `ITemplateEngineConfig` | - | Zentrale Konfiguration | + +#### Konstruktoren + +```csharp +// 1. Mit DataModel und Template +public TemplateEngine(T templateDataModel, string stringTemplate) + +// 2. Nur mit DataModel +public TemplateEngine(T templateDataModel) + +// 3. Parameterlos +public TemplateEngine() +``` + +#### Methoden + +##### CreateStringFromTemplate() + +```csharp +public string CreateStringFromTemplate() +``` + +**Beschreibung:** Erstellt String aus aktuellem TemplateString und TemplateDataModel. + +**Rückgabe:** Verarbeiteter String mit ersetzten Platzhaltern. + +**Beispiel:** +```csharp +var engine = new TemplateEngine(); +engine.TemplateDataModel = person; +engine.TemplateString = "Hallo ${FirstName}!"; +string result = engine.CreateStringFromTemplate(); +``` + +--- + +##### CreateStringFromTemplate(string stringTemplate) + +```csharp +public string CreateStringFromTemplate(string stringTemplate = null) +``` + +**Parameter:** +- `stringTemplate` - Optionaler Template-String (überschreibt `TemplateString`) + +**Rückgabe:** Verarbeiteter String. + +**Beispiel:** +```csharp +var engine = new TemplateEngine(person); +string result = engine.CreateStringFromTemplate("${FirstName} ${LastName}"); +``` + +--- + +##### CreateStringFromTemplate(T templateDataModel) + +```csharp +public string CreateStringFromTemplate(T templateDataModel) +``` + +**Parameter:** +- `templateDataModel` - Neues DataModel (überschreibt `TemplateDataModel`) + +**Rückgabe:** Verarbeiteter String. + +**Beispiel:** +```csharp +var engine = new TemplateEngine(); +engine.TemplateString = "Hallo ${FirstName}!"; +string result = engine.CreateStringFromTemplate(person); +``` + +--- + +##### CreateStringFromTemplate(T templateDataModel, string stringTemplate) + +```csharp +public string CreateStringFromTemplate(T templateDataModel, string stringTemplate) +``` + +**Parameter:** +- `templateDataModel` - Neues DataModel +- `stringTemplate` - Neuer Template-String + +**Rückgabe:** Verarbeiteter String. + +**Beispiel:** +```csharp +var engine = new TemplateEngine(); +string result = engine.CreateStringFromTemplate(person, "Hallo ${FirstName}!"); +``` + +--- + +### Template-Syntax + +#### Property-Platzhalter + +```csharp +// DataModel +public class Person { + public string FirstName { get; set; } + public int Age { get; set; } +} + +// Template +"Name: ${FirstName}, Alter: ${Age}" +``` + +#### Methoden-Platzhalter + +```csharp +// DataModel +public class Person { + public string GetFullName() { + return $"{FirstName} {LastName}"; + } +} + +// Template +"Vollständiger Name: ${GetFullName()}" +``` + +**Wichtig:** Nur parameterlose öffentliche Methoden werden unterstützt! + +#### Custom Delimiters + +```csharp +var engine = new TemplateEngine(person, "[[FirstName]] [[LastName]]"); +engine.OpeningDelimiter = "[["; +engine.CloseingDelimiter = "]]"; +string result = engine.CreateStringFromTemplate(); +``` + +--- + +## RazorTemplateEngine + +### RazorTemplateEngine + +```csharp +public class RazorTemplateEngine : ITemplateEngine + where T : TemplateDataModel +``` + +**Beschreibung:** Template-Engine für Razor-Syntax (.cshtml). + +**Einschränkung:** Benötigt `TemplateDataModel` als Basis-Klasse für DataModel. + +#### Konstruktoren + +```csharp +// 1. Mit IRazorEngine (für Dependency Injection) +public RazorTemplateEngine(IRazorEngine razorEngine) + +// 2. Parameterlos (erstellt eigene RazorEngine-Instanz) +public RazorTemplateEngine() + +// 3. Mit DataModel und Template +public RazorTemplateEngine(T dataModel, string templateString) +``` + +#### Eigenschaften + +| Eigenschaft | Typ | Beschreibung | +|-------------|-----|--------------| +| `TemplateDataModel` | `T` | Datenmodell (muss von `TemplateDataModel` erben) | +| `TemplateString` | `string` | Razor-Template (.cshtml Syntax) | +| `Config` | `ITemplateEngineConfig` | Konfiguration | + +**Hinweis:** `OpeningDelimiter`, `CloseingDelimiter`, `NullStringValue` und `CultureInfo` werden ignoriert (Razor hat eigene Syntax). + +#### Methoden + +##### CreateStringFromTemplate() + +```csharp +public string CreateStringFromTemplate(string csHtmlTemplate = null) +``` + +**Parameter:** +- `csHtmlTemplate` - Optionales Razor-Template (überschreibt `TemplateString`) + +**Rückgabe:** Gerendeter HTML-String. + +**Beispiel:** +```csharp +var engine = new RazorTemplateEngine(); +engine.TemplateString = "@Model.FirstName @Model.LastName"; +string result = engine.CreateStringFromTemplate(person); +``` + +--- + +##### CreateStringFromTemplate(T templateDataModel) + +```csharp +public string CreateStringFromTemplate(T templateDataModel) +``` + +**Parameter:** +- `templateDataModel` - Neues DataModel + +**Rückgabe:** Gerendeter HTML-String. + +--- + +##### CreateStringFromTemplate(T templateDataModel, string csHtmlTemplate) + +```csharp +public string CreateStringFromTemplate(T templateDataModel, string csHtmlTemplate) +``` + +**Parameter:** +- `templateDataModel` - Neues DataModel +- `csHtmlTemplate` - Neues Razor-Template + +**Rückgabe:** Gerendeter HTML-String. + +--- + +### Razor-Template-Syntax + +```cshtml +@* Person-Daten anzeigen *@ +

    @Model.FirstName @Model.LastName

    + +@* Bedingte Anzeige *@ +@if (Model.Age >= 18) { +

    Volljährig

    +} else { +

    Minderjährig

    +} + +@* Listen iterieren *@ +
      +@foreach(var tag in Model.Tags) { +
    • @tag
    • +} +
    + +@* Verschachtelte Objekte *@ +

    Adresse: @Model.Address.Street, @Model.Address.PostCode

    +``` + +--- + +## Interfaces + +### ITemplateEngine + +```csharp +public interface ITemplateEngine +{ + string CloseingDelimiter { get; set; } + ITemplateEngineConfig Config { get; set; } + CultureInfo CultureInfo { get; set; } + string NullStringValue { get; set; } + string OpeningDelimiter { get; set; } + T TemplateDataModel { get; set; } + string TemplateString { get; set; } + + string CreateStringFromTemplate(string stringTemplate = null); + string CreateStringFromTemplate(T templateDataModel); + string CreateStringFromTemplate(T templateDataModel, string stringTemplate); +} +``` + +**Beschreibung:** Gemeinsames Interface für beide Template-Engine-Typen. + +**Verwendung:** Ermöglicht austauschbare Nutzung von TemplateEngine und RazorTemplateEngine. + +**Beispiel:** +```csharp +public void ProcessTemplate(ITemplateEngine engine, Person person) { + string result = engine.CreateStringFromTemplate(person); + // Funktioniert mit beiden Engine-Typen +} +``` + +--- + +### ITemplateEngineConfig + +```csharp +public interface ITemplateEngineConfig +{ + string OpeningDelimiter { get; set; } + string CloseingDelimiter { get; set; } + string TemplateString { get; set; } + T TemplateDataModel { get; set; } + string NullStringValue { get; set; } + CultureInfo CultureInfo { get; set; } +} +``` + +**Beschreibung:** Interface für Template-Engine-Konfiguration. + +--- + +## Konfiguration + +### TemplateEngineConfig + +```csharp +public class TemplateEngineConfig : ITemplateEngineConfig +``` + +**Beschreibung:** Konfigurationsklasse für zentrale Engine-Einstellungen. + +#### Beispiel + +```csharp +var config = new TemplateEngineConfig { + OpeningDelimiter = "{{", + CloseingDelimiter = "}}", + TemplateString = "Hallo {{FirstName}}!", + TemplateDataModel = person, + NullStringValue = "???", + CultureInfo = CultureInfo.GetCultureInfo("de-DE") +}; + +var engine = new TemplateEngine(); +engine.Config = config; + +string result = engine.CreateStringFromTemplate(); +``` + +**Vorteile:** +- Zentrale Konfiguration +- Wiederverwendbar +- Testfreundlich + +--- + +## Erweiterungsmethoden + +### TemplateEngineExtensions + +```csharp +public static class TemplateEngineExtensions +``` + +#### CreateStringFromTemplateWithJson + +```csharp +public static string CreateStringFromTemplateWithJson( + this ITemplateEngine templateEngine, + string jsonData) +``` + +**Beschreibung:** Deserialisiert JSON zu DataModel und erstellt String. + +**Parameter:** +- `jsonData` - JSON-String mit Daten + +**Rückgabe:** Verarbeiteter String. + +**Beispiel:** +```csharp +string json = "{\"FirstName\":\"Max\",\"LastName\":\"Mustermann\"}"; +var engine = new TemplateEngine(); +engine.TemplateString = "Hallo ${FirstName}!"; +string result = engine.CreateStringFromTemplateWithJson(json); +// Ergebnis: "Hallo Max!" +``` + +--- + +#### LoadTemplateFromFile + +```csharp +public static void LoadTemplateFromFile( + this ITemplateEngine templateEngine, + string path) +``` + +**Beschreibung:** Lädt Template-String aus Datei. + +**Parameter:** +- `path` - Dateipfad zum Template + +**Beispiel:** +```csharp +var engine = new TemplateEngine(person); +engine.LoadTemplateFromFile("templates/greeting.txt"); +string result = engine.CreateStringFromTemplate(); +``` + +**Template-Datei (greeting.txt):** +``` +Hallo ${FirstName} ${LastName}! +Ihr Alter: ${Age} +``` + +--- + +## Datentypen + +### Unterstützte Typen (TemplateEngine) + +Die `TemplateEngine` Klasse unterstützt folgende Datentypen für Properties: + +#### Primitive Typen +- `string` +- `byte` +- `sbyte` +- `char` +- `short` (Int16) +- `ushort` (UInt16) +- `int` (Int32) +- `uint` (UInt32) +- `long` (Int64) +- `ulong` (UInt64) + +#### Numerische Typen +- `decimal` +- `double` + +#### Weitere Typen +- `DateTime` +- `bool` (Boolean) + +#### Nicht unterstützte Typen +- **Object** (generisches object) +- **Custom Classes** (eigene Klassen) +- **Collections** (List, Array, Dictionary, IEnumerable, etc.) + +**Workaround für Collections:** Verwenden Sie `RazorTemplateEngine` für komplexe Datenstrukturen. + +--- + +### TemplateDataModel + +```csharp +public class TemplateDataModel : RazorEngineTemplateBase +{ + [JsonIgnore] + public new T Model { get; set; } + + public string GetNullstringValue() +} +``` + +**Beschreibung:** Basis-Klasse für DataModels in `RazorTemplateEngine`. + +**Verwendung:** +```csharp +public class Person : TemplateDataModel { + public string FirstName { get; set; } + public string LastName { get; set; } + public int Age { get; set; } + public List Tags { get; set; } +} +``` + +**Wichtig:** Nur für `RazorTemplateEngine` erforderlich, nicht für `TemplateEngine`. + +--- + +## Kulturabhängige Formatierung + +### CultureInfo-Verwendung + +```csharp +var person = new Person { + Salary = 1234.56, + BirthDate = new DateTime(1990, 5, 15) +}; + +// Deutsche Formatierung +var engineDE = new TemplateEngine(person, "Gehalt: ${Salary}, Geburt: ${BirthDate}"); +engineDE.CultureInfo = CultureInfo.GetCultureInfo("de-DE"); +string resultDE = engineDE.CreateStringFromTemplate(); +// Ergebnis: "Gehalt: 1234,56, Geburt: 15.05.1990 00:00:00" + +// US-Formatierung +var engineUS = new TemplateEngine(person, "Salary: ${Salary}, Birth: ${BirthDate}"); +engineUS.CultureInfo = CultureInfo.GetCultureInfo("en-US"); +string resultUS = engineUS.CreateStringFromTemplate(); +// Ergebnis: "Salary: 1234.56, Birth: 5/15/1990 12:00:00 AM" +``` + +--- + +## Fehlerbehandlung + +### NotSupportedException + +Wird geworfen, wenn ein nicht unterstützter Datentyp verwendet wird: + +```csharp +public class Person { + public string Name { get; set; } + public List Tags { get; set; } // Nicht unterstützt! +} + +var engine = new TemplateEngine(person, "${Tags}"); +// Wirft: NotSupportedException: Type 'System.Collections.Generic.List`1[System.String]' not supported +``` + +**Lösung:** Verwenden Sie `RazorTemplateEngine` für Collections. + +--- + +## Best Practices + +### 1. Typsichere Nutzung mit Generics + +```csharp +// ✅ Gut: Typsicher +var engine = new TemplateEngine(person, template); + +// ❌ Vermeiden: Untypisiert +var engine = new TemplateEngine(person, template); +``` + +### 2. Config-Objekt für Wiederverwendung + +```csharp +// ✅ Gut: Wiederverwendbare Konfiguration +var config = new TemplateEngineConfig { + OpeningDelimiter = "{{", + CloseingDelimiter = "}}", + NullStringValue = "N/A" +}; + +var engine1 = new TemplateEngine { Config = config }; +var engine2 = new TemplateEngine { Config = config }; +``` + +### 3. Erweiterungsmethoden nutzen + +```csharp +// ✅ Gut: Fluent API +var engine = new TemplateEngine(); +engine.LoadTemplateFromFile("template.txt"); +string result = engine.CreateStringFromTemplate(person); + +// ❌ Vermeiden: Manuelles File-Handling +string template = File.ReadAllText("template.txt"); +var engine = new TemplateEngine(person, template); +``` + +### 4. RazorTemplateEngine für komplexe Szenarien + +```csharp +// ✅ Gut: RazorTemplateEngine für Listen +var engine = new RazorTemplateEngine(); +engine.TemplateString = "@foreach(var tag in Model.Tags) {
  • @tag
  • }"; + +// ❌ Nicht möglich: TemplateEngine unterstützt keine Collections +var engine = new TemplateEngine(person, "${Tags}"); // Fehler! +``` + +--- + +**Letzte Aktualisierung:** Dezember 2025 +**Commit-Referenz:** 5c37e68 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..7103f46 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,378 @@ +# Architektur-Übersicht + +**Commit-Referenz:** 5c37e68 +**Dokumentations-Stand:** Dezember 2025 + +--- + +## Inhaltsverzeichnis + +1. [Überblick](#überblick) +2. [Architektur-Diagramme](#architektur-diagramme) +3. [Komponenten](#komponenten) +4. [Datenfluss](#datenfluss) +5. [Design-Entscheidungen](#design-entscheidungen) + +--- + +## Überblick + +MbSoftLab.TemplateEngine.Core ist eine .NET 8.0 Bibliothek, die zwei verschiedene Template-Engine-Implementierungen bereitstellt: + +1. **TemplateEngine** - Einfacher, schneller String-basierter Template-Engine +2. **RazorTemplateEngine** - Komplexer Razor-basierter Template-Engine für HTML + +Beide implementieren das gemeinsame `ITemplateEngine` Interface. + +--- + +## Architektur-Diagramme + +### Gesamt-Architektur + +```mermaid +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 "External Dependencies" + 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 +``` + +### Klassen-Hierarchie + +```mermaid +classDiagram + class ITemplateEngine~T~ { + <> + +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~ { + <> + +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~ + RazorEngineTemplateBase <|-- TemplateDataModel~T~ + TemplateEngine~T~ --> ITemplateEngineConfig~T~ + RazorTemplateEngine~T~ --> ITemplateEngineConfig~T~ + RazorTemplateEngine~T~ --> TemplateDataModel~T~ +``` + +### Template-Verarbeitungs-Pipeline (TemplateEngine) + +```mermaid +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 +``` + +### Template-Verarbeitungs-Pipeline (RazorTemplateEngine) + +```mermaid +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 +``` + +--- + +## Komponenten + +### 1. Template Engines + +#### TemplateEngine +- **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 + +#### RazorTemplateEngine +- **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. + +### 2. Datenverarbeitung + +#### TemplateDataModelProcessor +- **Verantwortung:** Verarbeitet TemplateDataModel-Klassen +- **Funktionen:** + - Extrahiert Properties via Reflection + - Extrahiert parameterlose öffentliche Methoden + - Filtert Basis-Klassen-Methoden (Blacklist) + - Delegiert Wert-Ersetzung an PlaceholderValueReplacer + +#### 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 + +#### ReplacementActionCollection +- **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 + +### 3. Konfiguration + +#### ITemplateEngineConfig / TemplateEngineConfig +- **Zweck:** Zentrale Konfiguration für Template-Engines +- **Einstellungen:** + - Delimiter (OpeningDelimiter, CloseingDelimiter) + - NULL-Wert-String + - CultureInfo für Formatierung + - TemplateDataModel und TemplateString + +### 4. Erweiterungen + +#### TemplateEngineExtensions +- **CreateStringFromTemplateWithJson:** JSON-Deserialisierung + Template-Verarbeitung +- **LoadTemplateFromFile:** Lädt Template-String aus Datei + +--- + +## Datenfluss + +### Einfacher TemplateEngine-Ablauf + +``` +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 +``` + +### RazorTemplateEngine-Ablauf + +``` +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 +``` + +--- + +## Design-Entscheidungen + +### 1. Zwei Template-Engine-Typen + +**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 + +### 2. Reflection-basierte Property-Verarbeitung + +**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 + +### 3. Typ-spezifische Ersetzungs-Actions + +**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 + +### 4. Immutable Delimiter nach Trim + +**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) + +### 5. Blacklist für Methoden + +**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 + +### 6. .NET 8.0 als Target Framework + +**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 + +--- + +## Erweiterungspunkte + +### Zukünftige Erweiterungsmöglichkeiten + +1. **Template-Caching:** Kompilierte Razor-Templates cachen für bessere Performance +2. **Async-Support:** Asynchrone Template-Verarbeitung +3. **Collection-Support in TemplateEngine:** Iteration über Listen direkt im Template +4. **Methoden mit Parametern:** Unterstützung für Methoden-Aufrufe mit Argumenten +5. **Custom Type Formatters:** Benutzer-definierte Formatierung für eigene Typen +6. **Template-Vererbung:** Include/Import von Templates +7. **Partial Templates:** Wiederverwendbare Template-Fragmente + +--- + +**Letzte Aktualisierung:** Dezember 2025 +**Commit-Referenz:** 5c37e68 diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..529f41c --- /dev/null +++ b/docs/development.md @@ -0,0 +1,627 @@ +# Entwickler-Leitfaden + +**Commit-Referenz:** 5c37e68 +**Dokumentations-Stand:** Dezember 2025 + +--- + +## Inhaltsverzeichnis + +1. [Entwicklungsumgebung einrichten](#entwicklungsumgebung-einrichten) +2. [Projekt-Struktur](#projekt-struktur) +3. [Build und Tests](#build-und-tests) +4. [Code-Konventionen](#code-konventionen) +5. [Contribution Guidelines](#contribution-guidelines) +6. [CI/CD Pipeline](#cicd-pipeline) +7. [Versionierung](#versionierung) +8. [Debugging-Tipps](#debugging-tipps) + +--- + +## Entwicklungsumgebung einrichten + +### Voraussetzungen + +- **.NET 8.0 SDK** oder höher +- **IDE:** Visual Studio 2022, Visual Studio Code, oder JetBrains Rider +- **Git** für Versionskontrolle + +### Installation + +```bash +# Repository klonen +git clone https://github.com/mbsoftlab/MbSoftLab.TemplateEngine.Core.git +cd MbSoftLab.TemplateEngine.Core + +# Dependencies wiederherstellen +dotnet restore + +# Projekt bauen +dotnet build + +# Tests ausführen +dotnet test +``` + +### Empfohlene VS Code Extensions + +- C# Dev Kit +- .NET Extension Pack +- NuGet Package Manager +- EditorConfig for VS Code + +### Empfohlene Visual Studio Workloads + +- .NET Desktop-Entwicklung +- ASP.NET- und Webentwicklung + +--- + +## Projekt-Struktur + +``` +MbSoftLab.TemplateEngine.Core/ +├── .github/ +│ └── workflows/ # GitHub Actions CI/CD +│ ├── BuildFromDevelop.yml +│ ├── BuildFromMaster.yml +│ └── Release.yml +├── MbSoftLab.TemplateEngine.Core/ # Haupt-Bibliothek +│ ├── ITemplateEngine.cs # Interface für Template-Engines +│ ├── TemplateEngine.cs # Simple Template-Engine +│ ├── RazorTemplateEngine.cs # Razor-basierte Engine +│ ├── TemplateDataModel.cs # Basis-Klasse für Razor-Models +│ ├── TemplateDataModelProcessor.cs # Property/Methoden-Verarbeitung +│ ├── PlaceholderValueRaplacer.cs # Platzhalter-Ersetzung +│ ├── ReplacementActionCollection.cs # Typ-spezifische Actions +│ ├── ITemplateEngineConfig.cs # Konfigurations-Interface +│ ├── TemplateEngineConfig.cs # Konfigurations-Implementierung +│ ├── TemplateEngineExtensions.cs # Erweiterungsmethoden +│ └── MbSoftLab.TemplateEngine.Core.csproj # Projekt-Datei +├── MbSoftLab.TemplateEngine.Core.Tests/ # Unit-Tests +│ ├── TemplateEngineUnitTest.cs +│ ├── RazorTemplateEngineUnitTest.cs +│ ├── TemplateDataModelDummy.cs # Test-Fixtures +│ └── *.cs # Weitere Test-Dateien +├── MbSoftlab.TemplateEngine.Core.Demo/ # Demo-Anwendung +│ ├── Program.cs +│ ├── Person.cs +│ ├── Address.cs +│ ├── Order.cs +│ └── TestModel.cshtml # Razor-Template-Beispiel +├── docs/ # Dokumentation +│ ├── architecture/ +│ ├── api/ +│ ├── examples/ +│ └── development/ +├── CHANGELOG.md # Versions-Historie +├── RELEASENOTES.md # Release-Informationen +├── README.md # Haupt-Dokumentation +└── MbSoftLab.TemplateEngine.Core.sln # Solution-Datei +``` + +--- + +## Build und Tests + +### Lokaler Build + +```bash +# Debug-Build +dotnet build + +# Release-Build +dotnet build --configuration Release + +# NuGet-Package erstellen +dotnet pack --configuration Release +``` + +**Output:** Das NuGet-Package wird in `bin/Release/` erstellt. + +### Tests ausführen + +```bash +# Alle Tests +dotnet test + +# Mit Verbose-Output +dotnet test --verbosity detailed + +# Nur spezifische Tests +dotnet test --filter "FullyQualifiedName~TemplateEngineUnitTest" + +# Code Coverage (optional) +dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover +``` + +### Demo-Anwendung ausführen + +```bash +cd MbSoftlab.TemplateEngine.Core.Demo +dotnet run +``` + +Die Demo-Anwendung zeigt ein Razor-Template-Beispiel und öffnet das Ergebnis im Browser. + +--- + +## Code-Konventionen + +### Namenskonventionen + +- **Klassen:** PascalCase (`TemplateEngine`, `PlaceholderValueRaplacer`) +- **Interfaces:** PascalCase mit `I`-Prefix (`ITemplateEngine`) +- **Properties:** PascalCase (`OpeningDelimiter`) +- **Private Felder:** camelCase mit `_`-Prefix (`_outputString`) +- **Methoden:** PascalCase (`CreateStringFromTemplate`) +- **Parameter:** camelCase (`templateDataModel`) + +### Code-Stil + +```csharp +// ✅ Gut +public class TemplateEngine +{ + private string _templateString; + + public string TemplateString + { + get => _templateString; + set => _templateString = value; + } + + public string CreateStringFromTemplate() + { + // Implementation + } +} + +// ❌ Vermeiden +public class templateEngine +{ + public string templatestring; + + public string create_string() { } +} +``` + +### XML-Dokumentation + +Alle öffentlichen APIs müssen XML-Dokumentation haben: + +```csharp +/// +/// Ersetzt alle Properties von templateDataModel im stringTemplate. +/// Die Property-Namen müssen mit den Platzhaltern übereinstimmen. +/// +/// Datenmodell mit Properties +/// Template mit Platzhaltern +/// Verarbeiteter String mit ersetzten Platzhaltern +public string CreateStringFromTemplate(T templateDataModel, string stringTemplate) +{ + // Implementation +} +``` + +### EditorConfig + +Das Projekt verwendet `.editorconfig` für konsistente Code-Formatierung: + +```ini +[*.cs] +indent_style = space +indent_size = 4 +end_of_line = crlf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +``` + +--- + +## Contribution Guidelines + +### Branch-Strategie + +- **master:** Produktions-Code (stabil) +- **develop:** Entwicklungs-Branch (neueste Features) +- **feature/\*:** Feature-Branches (von develop abzweigen) +- **bugfix/\*:** Bugfix-Branches +- **hotfix/\*:** Dringende Fixes für master + +### Workflow + +1. **Fork erstellen** oder auf **develop** Branch wechseln + ```bash + git checkout develop + git pull origin develop + ``` + +2. **Feature-Branch erstellen** + ```bash + git checkout -b feature/mein-neues-feature + ``` + +3. **Änderungen implementieren** + - Code schreiben + - Tests hinzufügen + - Dokumentation aktualisieren + +4. **Tests ausführen** + ```bash + dotnet test + ``` + +5. **Commit** + ```bash + git add . + git commit -m "feat: Beschreibung des Features" + ``` + +6. **Push und Pull Request** + ```bash + git push origin feature/mein-neues-feature + ``` + Dann Pull Request auf GitHub erstellen. + +### Commit-Message-Konventionen + +Folgen Sie [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat: Neue Funktion hinzufügen +fix: Bug beheben +docs: Dokumentation aktualisieren +style: Code-Formatierung (keine funktionale Änderung) +refactor: Code-Refactoring +test: Tests hinzufügen oder ändern +chore: Build-Prozess oder Tools ändern +``` + +**Beispiele:** +``` +feat: RazorTemplateEngine für HTML-Templates hinzufügen +fix: NULL-Wert-Behandlung in PlaceholderValueRaplacer korrigieren +docs: API-Dokumentation für CreateStringFromTemplate erweitern +test: Unit-Tests für Custom Delimiters hinzufügen +``` + +--- + +## CI/CD Pipeline + +### GitHub Actions Workflows + +#### 1. BuildFromDevelop.yml + +**Trigger:** Push oder Pull Request auf `develop` Branch + +**Schritte:** +- Checkout Code +- Setup .NET 8.0 +- Restore Dependencies +- Build (Debug) +- Run Tests + +```yaml +name: BuildFromDevelop +on: + push: + branches: [ develop ] + pull_request: + branches: [ develop ] + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + - name: Restore + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal +``` + +#### 2. BuildFromMaster.yml + +**Trigger:** Push auf `master` Branch + +**Schritte:** Identisch zu BuildFromDevelop, aber für master. + +#### 3. Release.yml + +**Trigger:** GitHub Release wird veröffentlicht + +**Schritte:** +- Checkout Code +- Setup .NET 8.0 +- Restore Dependencies +- Build (Release) +- Create NuGet Package +- Publish to NuGet.org + +```yaml +name: Release +on: + release: + types: + - published + +jobs: + publish-nuget: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + - name: Restore + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Pack + run: dotnet pack MbSoftLab.TemplateEngine.Core/MbSoftLab.TemplateEngine.Core.csproj --configuration Release --no-restore -o ./artifacts + - name: Push to NuGet + run: dotnet nuget push ./artifacts/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate +``` + +### Lokale Build-Validierung vor Push + +```bash +# Vor jedem Push ausführen +dotnet restore +dotnet build --configuration Release +dotnet test +dotnet pack --configuration Release +``` + +--- + +## Versionierung + +### Semantic Versioning + +Projekt folgt [Semantic Versioning 2.0.0](https://semver.org/): + +``` +MAJOR.MINOR.PATCH[-PRERELEASE] + +1.0.8-preview2 +│ │ │ └─ Pre-Release-Identifier +│ │ └─── PATCH: Bugfixes +│ └───── MINOR: Neue Features (abwärtskompatibel) +└─────── MAJOR: Breaking Changes +``` + +### Versions-Einstellungen + +In `MbSoftLab.TemplateEngine.Core.csproj`: + +```xml + + 1.0.8.2 + 1.0.8.2 + 1.0.8 + 1.0.8-preview2 + +``` + +**Ändern für neue Version:** +1. `AssemblyVersion` erhöhen (für .NET-Assemblies) +2. `Version` anpassen (NuGet-Package-Hauptversion) +3. `PackageVersion` setzen (inklusive Pre-Release-Suffix falls notwendig) +4. CHANGELOG.md und RELEASENOTES.md aktualisieren + +--- + +## Debugging-Tipps + +### 1. Template-Verarbeitung debuggen + +```csharp +// Breakpoint vor und nach Verarbeitung setzen +var engine = new TemplateEngine(customer, template); + +// Template vor Verarbeitung prüfen +string beforeProcessing = engine.TemplateString; + +string result = engine.CreateStringFromTemplate(); + +// Ergebnis nach Verarbeitung prüfen +Console.WriteLine($"Vor: {beforeProcessing}"); +Console.WriteLine($"Nach: {result}"); +``` + +### 2. Reflection-Debugging + +```csharp +// Properties des DataModels inspizieren +var properties = customer.GetType().GetProperties(); +foreach (var prop in properties) +{ + var value = prop.GetValue(customer); + Console.WriteLine($"{prop.Name}: {value}"); +} +``` + +### 3. Razor-Kompilierung debuggen + +```csharp +try +{ + var razorEngine = new RazorTemplateEngine(); + razorEngine.TemplateString = razorTemplate; + string result = razorEngine.CreateStringFromTemplate(person); +} +catch (RazorEngineCompilationException ex) +{ + Console.WriteLine("Razor-Kompilierungs-Fehler:"); + Console.WriteLine(ex.Message); + Console.WriteLine("Errors:"); + foreach (var error in ex.Errors) + { + Console.WriteLine($" - {error}"); + } +} +``` + +### 4. Unit-Test-Debugging + +```bash +# Einzelnen Test mit Debugging ausführen +dotnet test --filter "MethodName=can_create_a_valid_string_from_template" + +# Visual Studio: Rechtsklick auf Test → "Debug Test" +# VS Code: "Debug Test" im Test Explorer +``` + +### 5. Performance-Analyse + +```csharp +using System.Diagnostics; + +var stopwatch = Stopwatch.StartNew(); +var engine = new TemplateEngine(customer, template); +string result = engine.CreateStringFromTemplate(); +stopwatch.Stop(); + +Console.WriteLine($"Template-Verarbeitung: {stopwatch.ElapsedMilliseconds}ms"); +``` + +--- + +## Erweiterte Entwicklungs-Themen + +### Neue Datentypen hinzufügen + +Um einen neuen Datentyp in `TemplateEngine` zu unterstützen: + +1. **ReplacementAction registrieren** in `PlaceholderValueRaplacer.cs`: + +```csharp +private void RegisterReplacementActions() +{ + _replacementActionCollection + // ... bestehende Actions ... + .AddReplacementAction(typeof(Guid), (placeholderValueName, value) => + ReplaceValueInOutputString(placeholderValueName, (Guid)value)); +} +``` + +2. **Tests hinzufügen** in `TemplateEngineUnitTest.cs`: + +```csharp +[Test] +public void can_handle_guid_values() +{ + var guid = Guid.NewGuid(); + var model = new { Id = guid }; + var engine = new TemplateEngine(model, "ID: ${Id}"); + string result = engine.CreateStringFromTemplate(); + Assert.AreEqual($"ID: {guid}", result); +} +``` + +### Custom Template-Engine erstellen + +Implementieren Sie `ITemplateEngine`: + +```csharp +public class MyCustomEngine : ITemplateEngine +{ + public string OpeningDelimiter { get; set; } + public string CloseingDelimiter { get; set; } + public T TemplateDataModel { get; set; } + public string TemplateString { get; set; } + public string NullStringValue { get; set; } + public CultureInfo CultureInfo { get; set; } + public ITemplateEngineConfig Config { get; set; } + + public string CreateStringFromTemplate(string stringTemplate = null) + { + // Eigene Implementierung + } + + public string CreateStringFromTemplate(T templateDataModel) + { + // Eigene Implementierung + } + + public string CreateStringFromTemplate(T templateDataModel, string stringTemplate) + { + // Eigene Implementierung + } +} +``` + +--- + +## Trouble-Shooting + +### Problem: Build schlägt fehl + +```bash +# Dependencies neu laden +dotnet restore --force +dotnet clean +dotnet build +``` + +### Problem: Tests schlagen fehl + +```bash +# Alle Build-Artefakte löschen +dotnet clean +rm -rf */bin */obj +dotnet build +dotnet test +``` + +### Problem: NuGet-Package kann nicht erstellt werden + +```bash +# Pack mit Verbose-Output +dotnet pack --configuration Release --verbosity detailed +``` + +### Problem: Razor-Templates funktionieren nicht + +**Prüfen:** +1. Erbt DataModel von `TemplateDataModel`? +2. Ist `@Model` in Template korrekt? +3. RazorEngineCore-Dependency installiert? + +```bash +dotnet list package | grep RazorEngineCore +``` + +--- + +## Ressourcen + +### Offizielle Dokumentation + +- [.NET 8.0 Dokumentation](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-8) +- [NuGet Package Dokumentation](https://learn.microsoft.com/nuget/) +- [GitHub Actions Dokumentation](https://docs.github.com/actions) + +### Dependencies + +- [RazorEngineCore](https://github.com/adoconnection/RazorEngineCore) + +### Code-Qualität + +- [CodeFactor](https://www.codefactor.io/repository/github/mbsoftlab/mbsoftlab.templateengine.core) + +--- + +**Letzte Aktualisierung:** Dezember 2025 +**Commit-Referenz:** 5c37e68 diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..61389dd --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,815 @@ +# Beispiele und Tutorials + +**Commit-Referenz:** 5c37e68 +**Dokumentations-Stand:** Dezember 2025 + +--- + +## Inhaltsverzeichnis + +1. [Schnellstart](#schnellstart) +2. [Einfache Beispiele](#einfache-beispiele) +3. [Fortgeschrittene Beispiele](#fortgeschrittene-beispiele) +4. [Razor-Templates](#razor-templates) +5. [Praxis-Szenarien](#praxis-szenarien) +6. [Tipps und Tricks](#tipps-und-tricks) + +--- + +## Schnellstart + +### Installation + +```bash +# NuGet Package Manager +Install-Package MbSoftLab.TemplateEngine.Core + +# .NET CLI +dotnet add package MbSoftLab.TemplateEngine.Core +``` + +### Erstes Beispiel (30 Sekunden) + +```csharp +using MbSoftLab.TemplateEngine.Core; + +// 1. Datenmodell erstellen +var person = new { FirstName = "Max", LastName = "Mustermann" }; + +// 2. Template definieren +string template = "Hallo ${FirstName} ${LastName}!"; + +// 3. Template-Engine initialisieren +var engine = new TemplateEngine(person, template); + +// 4. String erstellen +string result = engine.CreateStringFromTemplate(); + +Console.WriteLine(result); +// Output: Hallo Max Mustermann! +``` + +--- + +## Einfache Beispiele + +### Beispiel 1: Grundlegende Verwendung + +```csharp +using MbSoftLab.TemplateEngine.Core; + +public class Customer +{ + public string Name { get; set; } + public string Email { get; set; } + public int OrderCount { get; set; } +} + +// Daten +var customer = new Customer +{ + Name = "Anna Schmidt", + Email = "anna@example.com", + OrderCount = 5 +}; + +// Template +string template = @" +Kunde: ${Name} +E-Mail: ${Email} +Anzahl Bestellungen: ${OrderCount} +"; + +// Verarbeitung +var engine = new TemplateEngine(customer, template); +string result = engine.CreateStringFromTemplate(); + +Console.WriteLine(result); +``` + +**Output:** +``` +Kunde: Anna Schmidt +E-Mail: anna@example.com +Anzahl Bestellungen: 5 +``` + +--- + +### Beispiel 2: Property-Injection + +```csharp +// Engine ohne Daten erstellen +var engine = new TemplateEngine(); + +// Später Daten setzen +engine.TemplateDataModel = customer; +engine.TemplateString = "Hallo ${Name}!"; + +// Verarbeiten +string result = engine.CreateStringFromTemplate(); +``` + +**Vorteil:** Flexibel für Dependency Injection und Testszenarien. + +--- + +### Beispiel 3: Custom Delimiters + +```csharp +var customer = new Customer { Name = "Bob" }; + +var engine = new TemplateEngine(customer, "[[Name]]"); +engine.OpeningDelimiter = "[["; +engine.CloseingDelimiter = "]]"; + +string result = engine.CreateStringFromTemplate(); +// Output: Bob +``` + +**Use-Case:** Konflikte mit anderen Template-Syntaxen vermeiden (z.B. Angular, Vue.js). + +--- + +### Beispiel 4: NULL-Wert-Behandlung + +```csharp +var customer = new Customer +{ + Name = "Charlie", + Email = null // NULL-Wert +}; + +var engine = new TemplateEngine(customer, "E-Mail: ${Email}"); +string result = engine.CreateStringFromTemplate(); +// Output: E-Mail: NULL + +// Custom NULL-String +engine.NullStringValue = "Keine Angabe"; +result = engine.CreateStringFromTemplate(); +// Output: E-Mail: Keine Angabe +``` + +--- + +### Beispiel 5: Kultur-spezifische Formatierung + +```csharp +public class Product +{ + public string Name { get; set; } + public decimal Price { get; set; } + public DateTime Available { get; set; } +} + +var product = new Product +{ + Name = "Laptop", + Price = 1299.99m, + Available = new DateTime(2025, 12, 24) +}; + +// Deutsche Formatierung +var engineDE = new TemplateEngine(product, + "Produkt: ${Name}\nPreis: ${Price}\nVerfügbar ab: ${Available}"); +engineDE.CultureInfo = System.Globalization.CultureInfo.GetCultureInfo("de-DE"); +Console.WriteLine(engineDE.CreateStringFromTemplate()); + +// Output: +// Produkt: Laptop +// Preis: 1299,99 +// Verfügbar ab: 24.12.2025 00:00:00 +``` + +--- + +### Beispiel 6: Template aus Datei laden + +**Template-Datei:** `email-template.txt` +``` +Sehr geehrte/r ${Name}, + +vielen Dank für Ihre ${OrderCount} Bestellungen. + +Mit freundlichen Grüßen +Ihr Team +``` + +**C#-Code:** +```csharp +var customer = new Customer +{ + Name = "Diana Weber", + OrderCount = 3 +}; + +var engine = new TemplateEngine(customer); +engine.LoadTemplateFromFile("email-template.txt"); +string result = engine.CreateStringFromTemplate(); + +Console.WriteLine(result); +``` + +--- + +### Beispiel 7: Methoden in Templates + +```csharp +public class Invoice +{ + public string InvoiceNumber { get; set; } + public decimal NetAmount { get; set; } + public decimal TaxRate { get; set; } + + // Parameterlose Methode + public decimal GetGrossAmount() + { + return NetAmount * (1 + TaxRate); + } + + public string GetFormattedInvoiceNumber() + { + return $"INV-{InvoiceNumber}"; + } +} + +var invoice = new Invoice +{ + InvoiceNumber = "2025-001", + NetAmount = 100m, + TaxRate = 0.19m +}; + +string template = @" +Rechnungsnummer: ${GetFormattedInvoiceNumber()} +Nettobetrag: ${NetAmount} +Bruttobetrag: ${GetGrossAmount()} +"; + +var engine = new TemplateEngine(invoice, template); +string result = engine.CreateStringFromTemplate(); +``` + +**Output:** +``` +Rechnungsnummer: INV-2025-001 +Nettobetrag: 100 +Bruttobetrag: 119 +``` + +**Wichtig:** Nur parameterlose öffentliche Methoden funktionieren! + +--- + +## Fortgeschrittene Beispiele + +### Beispiel 8: JSON-Daten verwenden + +```csharp +string jsonData = @" +{ + ""Name"": ""Eve Johnson"", + ""Email"": ""eve@example.com"", + ""OrderCount"": 7 +}"; + +var engine = new TemplateEngine(); +engine.TemplateString = "Kunde ${Name} hat ${OrderCount} Bestellungen."; + +string result = engine.CreateStringFromTemplateWithJson(jsonData); +// Output: Kunde Eve Johnson hat 7 Bestellungen. +``` + +--- + +### Beispiel 9: Konfigurationsobjekt verwenden + +```csharp +var config = new TemplateEngineConfig +{ + OpeningDelimiter = "{{", + CloseingDelimiter = "}}", + NullStringValue = "---", + TemplateString = "{{Name}} ({{Email}})", + TemplateDataModel = customer, + CultureInfo = System.Globalization.CultureInfo.GetCultureInfo("de-DE") +}; + +var engine = new TemplateEngine(); +engine.Config = config; + +string result = engine.CreateStringFromTemplate(); +``` + +**Vorteil:** Wiederverwendbare Konfiguration, ideal für Unit-Tests. + +--- + +### Beispiel 10: Mehrere Templates mit gleichen Daten + +```csharp +var customer = new Customer { Name = "Frank", Email = "frank@test.de" }; + +var emailEngine = new TemplateEngine(customer); +var smsEngine = new TemplateEngine(customer); + +// E-Mail-Template +emailEngine.TemplateString = "Hallo ${Name}, Ihre E-Mail: ${Email}"; +string email = emailEngine.CreateStringFromTemplate(); + +// SMS-Template (kürzer) +smsEngine.TemplateString = "Hallo ${Name}!"; +string sms = smsEngine.CreateStringFromTemplate(); +``` + +--- + +### Beispiel 11: Dynamisches Template-Switching + +```csharp +var customer = new Customer { Name = "Grace", OrderCount = 10 }; + +var engine = new TemplateEngine(customer); + +// Verschiedene Templates je nach Kontext +string template = customer.OrderCount > 5 + ? "Vielen Dank für Ihre ${OrderCount} Bestellungen, ${Name}!" + : "Hallo ${Name}, Sie haben ${OrderCount} Bestellungen."; + +engine.TemplateString = template; +string result = engine.CreateStringFromTemplate(); +``` + +--- + +## Razor-Templates + +### Beispiel 12: Einfaches Razor-Template + +```csharp +using MbSoftLab.TemplateEngine.Core; + +public class Person : TemplateDataModel +{ + public string FirstName { get; set; } + public string LastName { get; set; } + public int Age { get; set; } +} + +var person = new Person +{ + FirstName = "Hans", + LastName = "Müller", + Age = 35 +}; + +var engine = new RazorTemplateEngine(); + +string razorTemplate = @" +

    @Model.FirstName @Model.LastName

    +

    Alter: @Model.Age Jahre

    +"; + +engine.TemplateString = razorTemplate; +string html = engine.CreateStringFromTemplate(person); +``` + +**Output:** +```html +

    Hans Müller

    +

    Alter: 35 Jahre

    +``` + +--- + +### Beispiel 13: Razor mit Bedingungen + +```csharp +public class User : TemplateDataModel +{ + public string Name { get; set; } + public bool IsPremium { get; set; } + public int Points { get; set; } +} + +var user = new User +{ + Name = "Ines", + IsPremium = true, + Points = 1250 +}; + +string template = @" +
    +

    @Model.Name

    + + @if (Model.IsPremium) { + Premium-Mitglied + } + +

    Punkte: @Model.Points

    + + @if (Model.Points > 1000) { +

    Sie haben genug Punkte für eine Belohnung!

    + } +
    +"; + +var engine = new RazorTemplateEngine(user, template); +string html = engine.CreateStringFromTemplate(); +``` + +--- + +### Beispiel 14: Razor mit Listen (foreach) + +```csharp +public class ShoppingList : TemplateDataModel +{ + public string Owner { get; set; } + public List Items { get; set; } +} + +var list = new ShoppingList +{ + Owner = "Julia", + Items = new List { "Milch", "Brot", "Eier", "Butter" } +}; + +string template = @" +

    Einkaufsliste von @Model.Owner

    +
      +@foreach(var item in Model.Items) { +
    • @item
    • +} +
    +

    Gesamt: @Model.Items.Count Artikel

    +"; + +var engine = new RazorTemplateEngine(list, template); +string html = engine.CreateStringFromTemplate(); +``` + +**Output:** +```html +

    Einkaufsliste von Julia

    +
      +
    • Milch
    • +
    • Brot
    • +
    • Eier
    • +
    • Butter
    • +
    +

    Gesamt: 4 Artikel

    +``` + +--- + +### Beispiel 15: Razor mit verschachtelten Objekten + +```csharp +public class Address : TemplateDataModel
    +{ + public string Street { get; set; } + public string City { get; set; } + public string PostCode { get; set; } +} + +public class Customer : TemplateDataModel +{ + public string Name { get; set; } + public Address Address { get; set; } + public List Orders { get; set; } +} + +public class Order : TemplateDataModel +{ + public int Id { get; set; } + public decimal Total { get; set; } +} + +var customer = new Customer +{ + Name = "Klaus Werner", + Address = new Address + { + Street = "Hauptstraße 1", + City = "München", + PostCode = "80331" + }, + Orders = new List + { + new Order { Id = 1, Total = 49.99m }, + new Order { Id = 2, Total = 129.50m } + } +}; + +string template = @" +
    +

    @Model.Name

    + +
    +

    Adresse

    +

    @Model.Address.Street
    + @Model.Address.PostCode @Model.Address.City

    +
    + +
    +

    Bestellungen

    + + + + + + @foreach(var order in Model.Orders) { + + + + + } + +
    IDSumme
    @order.Id@order.Total.ToString(""C"")
    +
    +
    +"; + +var engine = new RazorTemplateEngine(customer, template); +string html = engine.CreateStringFromTemplate(); +``` + +--- + +### Beispiel 16: Razor-Template aus Datei laden + +**Template-Datei:** `invoice.cshtml` +```cshtml +@* Rechnungs-Template *@ + + + Rechnung @Model.InvoiceNumber + + +

    Rechnung @Model.InvoiceNumber

    + + + @foreach(var item in Model.Items) { + + + + + + } +
    @item.ProductName@item.Quantity@item.Price.ToString("C")
    + +

    Gesamt: @Model.Total.ToString("C")

    + + +``` + +**C#-Code:** +```csharp +var invoice = new Invoice +{ + InvoiceNumber = "2025-123", + Items = items, + Total = 299.99m +}; + +var engine = new RazorTemplateEngine(invoice); +engine.LoadTemplateFromFile("invoice.cshtml"); +string html = engine.CreateStringFromTemplate(); + +// HTML in Datei speichern +File.WriteAllText("invoice-2025-123.html", html); +``` + +--- + +## Praxis-Szenarien + +### Szenario 1: E-Mail-Versand + +```csharp +public class EmailService +{ + private readonly ITemplateEngine _engine; + + public EmailService() + { + _engine = new TemplateEngine(); + } + + public string GenerateWelcomeEmail(string userName, string email) + { + var data = new EmailData + { + UserName = userName, + Email = email, + RegistrationDate = DateTime.Now + }; + + _engine.LoadTemplateFromFile("templates/welcome-email.txt"); + return _engine.CreateStringFromTemplate(data); + } +} + +public class EmailData +{ + public string UserName { get; set; } + public string Email { get; set; } + public DateTime RegistrationDate { get; set; } +} +``` + +**Template:** `welcome-email.txt` +``` +Hallo ${UserName}, + +herzlich willkommen! + +Ihre E-Mail-Adresse: ${Email} +Registriert am: ${RegistrationDate} + +Viele Grüße +Ihr Team +``` + +--- + +### Szenario 2: Report-Generierung + +```csharp +public class ReportGenerator +{ + public string GenerateMonthlyReport(ReportData data) + { + var config = new TemplateEngineConfig + { + TemplateDataModel = data, + CultureInfo = CultureInfo.GetCultureInfo("de-DE"), + NullStringValue = "Keine Daten" + }; + + var engine = new TemplateEngine { Config = config }; + engine.LoadTemplateFromFile("templates/monthly-report.txt"); + + return engine.CreateStringFromTemplate(); + } +} +``` + +--- + +### Szenario 3: HTML-Berichte mit Razor + +```csharp +public class HtmlReportService +{ + public void GenerateAndSaveReport(SalesData data, string outputPath) + { + var engine = new RazorTemplateEngine(); + engine.LoadTemplateFromFile("templates/sales-report.cshtml"); + + string html = engine.CreateStringFromTemplate(data); + + File.WriteAllText(outputPath, html); + } +} + +public class SalesData : TemplateDataModel +{ + public string Month { get; set; } + public decimal Revenue { get; set; } + public List TopSales { get; set; } +} +``` + +--- + +### Szenario 4: Konfigurations-Dateien generieren + +```csharp +public class ConfigGenerator +{ + public void GenerateAppConfig(AppSettings settings) + { + string template = @" +server.host=${Host} +server.port=${Port} +database.connection=${DatabaseConnection} +logging.level=${LogLevel} +"; + + var engine = new TemplateEngine(settings, template); + string config = engine.CreateStringFromTemplate(); + + File.WriteAllText("app.config", config); + } +} +``` + +--- + +## Tipps und Tricks + +### Tipp 1: Performance bei vielen gleichen Templates + +```csharp +// ❌ Nicht effizient +for (int i = 0; i < 1000; i++) { + var engine = new TemplateEngine(customers[i], template); + results[i] = engine.CreateStringFromTemplate(); +} + +// ✅ Effizient +var engine = new TemplateEngine(); +engine.TemplateString = template; +for (int i = 0; i < 1000; i++) { + results[i] = engine.CreateStringFromTemplate(customers[i]); +} +``` + +--- + +### Tipp 2: Template-Validierung + +```csharp +public bool ValidateTemplate(string template, Type modelType) +{ + try + { + var instance = Activator.CreateInstance(modelType); + var engine = new TemplateEngine(instance, template); + engine.CreateStringFromTemplate(); + return true; + } + catch + { + return false; + } +} +``` + +--- + +### Tipp 3: Collections mit TemplateEngine (Workaround) + +```csharp +// Statt Collections direkt zu verwenden +public class Report +{ + public string Item1 { get; set; } + public string Item2 { get; set; } + public string Item3 { get; set; } + + // Oder: Methode mit String-Join + public string GetAllItems() + { + return string.Join(", ", new[] { Item1, Item2, Item3 }); + } +} + +string template = "Items: ${GetAllItems()}"; +``` + +**Besser:** Verwenden Sie `RazorTemplateEngine` für echte Listen! + +--- + +### Tipp 4: Thread-Sicherheit + +```csharp +// ❌ Nicht thread-safe +var sharedEngine = new TemplateEngine(); + +// ✅ Thread-safe: Jeder Thread eigene Instanz +ThreadPool.QueueUserWorkItem(_ => { + var engine = new TemplateEngine(customer, template); + var result = engine.CreateStringFromTemplate(); +}); +``` + +--- + +### Tipp 5: Fehlerbehandlung + +```csharp +try +{ + var engine = new TemplateEngine(customer, template); + string result = engine.CreateStringFromTemplate(); +} +catch (NotSupportedException ex) +{ + Console.WriteLine($"Nicht unterstützter Typ: {ex.Message}"); + // Fallback zu RazorTemplateEngine +} +catch (Exception ex) +{ + Console.WriteLine($"Fehler bei Template-Verarbeitung: {ex.Message}"); +} +``` + +--- + +**Letzte Aktualisierung:** Dezember 2025 +**Commit-Referenz:** 5c37e68