Commit-Referenz: 5c37e68
Dokumentations-Stand: Dezember 2025
- Entwicklungsumgebung einrichten
- Projekt-Struktur
- Build und Tests
- Code-Konventionen
- Contribution Guidelines
- CI/CD Pipeline
- Versionierung
- Debugging-Tipps
- .NET 8.0 SDK oder höher
- IDE: Visual Studio 2022, Visual Studio Code, oder JetBrains Rider
- Git für Versionskontrolle
# 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- C# Dev Kit
- .NET Extension Pack
- NuGet Package Manager
- EditorConfig for VS Code
- .NET Desktop-Entwicklung
- ASP.NET- und Webentwicklung
MbSoftLab.TemplateEngine.Core/
├── .github/
│ └── workflows/ # GitHub Actions CI/CD
│ ├── BuildFromDevelop.yml
│ ├── BuildFromMaster.yml
│ └── Release.yml
├── MbSoftLab.TemplateEngine.Core/ # Haupt-Bibliothek (ohne Razor-Abhängigkeit)
│ ├── ITemplateEngine.cs # Interface für Template-Engines
│ ├── TemplateEngine.cs # Simple Template-Engine
│ ├── TemplateDataModel.cs # Datenmodell (ohne Razor-Basisklasse)
│ ├── 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 (referenzieren bei Bedarf Razor-Projekt)
│ ├── TemplateEngineUnitTest.cs
│ ├── RazorTemplateEngineUnitTest.cs
│ ├── TemplateDataModelDummy.cs # Test-Fixtures
│ └── *.cs # Weitere Test-Dateien
├── MbSoftlab.TemplateEngine.Core.Demo/ # Demo-Anwendung (Razor-Demo referenziert Razor-Projekt)
│ ├── 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.Razor/ # Optionales Razor-Erweiterungsprojekt
│ ├── RazorTemplateEngine.cs # Razor-basierte Engine
│ └── MbSoftLab.TemplateEngine.Core.Razor.csproj
└── MbSoftLab.TemplateEngine.Core.sln # Solution-Datei (enthält beide Projekte)
# Debug-Build
dotnet build
# Release-Build
dotnet build --configuration Release
# NuGet-Package erstellen
dotnet pack --configuration ReleaseOutput: Das NuGet-Package wird in bin/Release/ erstellt.
Das Razor-Feature ist als separates Paket/Projekt verfügbar.
# Razor-Erweiterung lokal referenzieren
dotnet add <IhrProjekt>.csproj reference MbSoftLab.TemplateEngine.Core.Razor/MbSoftLab.TemplateEngine.Core.Razor.csproj
# Oder als NuGet installieren
dotnet add package MbSoftLab.TemplateEngine.Core.RazorDie Projekte, die RazorTemplateEngine<T> verwenden, müssen die Razor-Erweiterung referenzieren oder das NuGet einsetzen.
# 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=opencovercd MbSoftlab.TemplateEngine.Core.Demo
dotnet runDie Demo-Anwendung zeigt ein Razor-Template-Beispiel und öffnet das Ergebnis im Browser.
- 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)
// ✅ Gut
public class TemplateEngine<T>
{
private string _templateString;
public string TemplateString
{
get => _templateString;
set => _templateString = value;
}
public string CreateStringFromTemplate()
{
// Implementation
}
}
// ❌ Vermeiden
public class templateEngine<t>
{
public string templatestring;
public string create_string() { }
}Alle öffentlichen APIs müssen XML-Dokumentation haben:
/// <summary>
/// Ersetzt alle Properties von templateDataModel im stringTemplate.
/// Die Property-Namen müssen mit den Platzhaltern übereinstimmen.
/// </summary>
/// <param name="templateDataModel">Datenmodell mit Properties</param>
/// <param name="stringTemplate">Template mit Platzhaltern</param>
/// <returns>Verarbeiteter String mit ersetzten Platzhaltern</returns>
public string CreateStringFromTemplate(T templateDataModel, string stringTemplate)
{
// Implementation
}Das Projekt verwendet .editorconfig für konsistente Code-Formatierung:
[*.cs]
indent_style = space
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true- master: Produktions-Code (stabil)
- develop: Entwicklungs-Branch (neueste Features)
- feature/*: Feature-Branches (von develop abzweigen)
- bugfix/*: Bugfix-Branches
- hotfix/*: Dringende Fixes für master
-
Fork erstellen oder auf develop Branch wechseln
git checkout develop git pull origin develop
-
Feature-Branch erstellen
git checkout -b feature/mein-neues-feature
-
Änderungen implementieren
- Code schreiben
- Tests hinzufügen
- Dokumentation aktualisieren
-
Tests ausführen
dotnet test -
Commit
git add . git commit -m "feat: Beschreibung des Features"
-
Push und Pull Request
git push origin feature/mein-neues-feature
Dann Pull Request auf GitHub erstellen.
Folgen Sie Conventional Commits:
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
Trigger: Push oder Pull Request auf develop Branch
Schritte:
- Checkout Code
- Setup .NET 8.0
- Restore Dependencies
- Build (Debug)
- Run Tests
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 normalTrigger: Push auf master Branch
Schritte: Identisch zu BuildFromDevelop, aber für master.
Trigger: GitHub Release wird veröffentlicht
Schritte:
- Checkout Code
- Setup .NET 8.0
- Restore Dependencies
- Build (Release)
- Create NuGet Package
- Publish to NuGet.org
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# Vor jedem Push ausführen
dotnet restore
dotnet build --configuration Release
dotnet test
dotnet pack --configuration ReleaseProjekt folgt Semantic Versioning 2.0.0:
MAJOR.MINOR.PATCH[-PRERELEASE]
1.0.8-preview2
│ │ │ └─ Pre-Release-Identifier
│ │ └─── PATCH: Bugfixes
│ └───── MINOR: Neue Features (abwärtskompatibel)
└─────── MAJOR: Breaking Changes
In MbSoftLab.TemplateEngine.Core.csproj:
<PropertyGroup>
<AssemblyVersion>1.0.8.2</AssemblyVersion>
<FileVersion>1.0.8.2</FileVersion>
<Version>1.0.8</Version>
<PackageVersion>1.0.8-preview2</PackageVersion>
</PropertyGroup>Ändern für neue Version:
AssemblyVersionerhöhen (für .NET-Assemblies)Versionanpassen (NuGet-Package-Hauptversion)PackageVersionsetzen (inklusive Pre-Release-Suffix falls notwendig)- CHANGELOG.md und RELEASENOTES.md aktualisieren
// Breakpoint vor und nach Verarbeitung setzen
var engine = new TemplateEngine<Customer>(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}");// Properties des DataModels inspizieren
var properties = customer.GetType().GetProperties();
foreach (var prop in properties)
{
var value = prop.GetValue(customer);
Console.WriteLine($"{prop.Name}: {value}");
}try
{
var razorEngine = new RazorTemplateEngine<Person>();
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}");
}
}# 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 Explorerusing System.Diagnostics;
var stopwatch = Stopwatch.StartNew();
var engine = new TemplateEngine<Customer>(customer, template);
string result = engine.CreateStringFromTemplate();
stopwatch.Stop();
Console.WriteLine($"Template-Verarbeitung: {stopwatch.ElapsedMilliseconds}ms");Um einen neuen Datentyp in TemplateEngine zu unterstützen:
- ReplacementAction registrieren in
PlaceholderValueRaplacer.cs:
private void RegisterReplacementActions()
{
_replacementActionCollection
// ... bestehende Actions ...
.AddReplacementAction(typeof(Guid), (placeholderValueName, value) =>
ReplaceValueInOutputString(placeholderValueName, (Guid)value));
}- Tests hinzufügen in
TemplateEngineUnitTest.cs:
[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);
}Implementieren Sie ITemplateEngine<T>:
public class MyCustomEngine<T> : ITemplateEngine<T>
{
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<T> 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
}
}# Dependencies neu laden
dotnet restore --force
dotnet clean
dotnet build# Alle Build-Artefakte löschen
dotnet clean
rm -rf */bin */obj
dotnet build
dotnet test# Pack mit Verbose-Output
dotnet pack --configuration Release --verbosity detailedPrüfen:
- Erbt DataModel von
TemplateDataModel<T>? - Ist
@Modelin Template korrekt? - RazorEngineCore-Dependency installiert?
dotnet list package | grep RazorEngineCoreLetzte Aktualisierung: Dezember 2025
Commit-Referenz: 5c37e68