Skip to content

Instantly share code, notes, and snippets.

@TorstenC
Last active May 1, 2024 22:53
Show Gist options
  • Save TorstenC/0207597e27b72f5bc8c8edebd7f8350f to your computer and use it in GitHub Desktop.
Save TorstenC/0207597e27b72f5bc8c8edebd7f8350f to your computer and use it in GitHub Desktop.
Shared Code für WPF-Anwendung und Blazor-Anwendung

Shared Code für WPF-Anwendung und Blazor-Anwendung

Da Blazor und WPF unterschiedliche Technologien mit eigenen Best Practices sind, müssen einige architektonische Überlegungen zu beachen, um eine maximale Wiederverwendung zu ermöglichen. Während direkte Wiederverwendung von View und ViewModel zwischen WPF und Blazor oft nicht praktikabel ist, kannst du das Design, die Architektur und vor allem das Model sowie Dienste oft wiederverwenden. Durch kluge Abstraktion und das Trennen von UI-spezifischer Logik und Geschäftslogik kannst du die Wiederverwendbarkeit maximieren und gleichzeitig die Plattform-spezifischen Stärken von WPF und Blazor nutzen.

Grundsätzliches

Strukturelle Überlegungen

  1. Model (M): Das Model, welches die Geschäftslogik und Datenzugriffsschicht beinhaltet, sollte idealerweise so gestaltet sein, dass es technologieunabhängig ist. Das bedeutet, dass es weder spezifische Abhängigkeiten von WPF noch von Blazor hat. Dies erleichtert die Wiederverwendung des Models sowohl in WPF als auch in Blazor.

  2. View (V): Die View ist spezifisch für die Plattform. WPF verwendet XAML für die Benutzeroberfläche, während Blazor entweder Razor Templates oder HTML/CSS verwendet. Hier gibt es keine direkte Wiederverwendungsmöglichkeit, aber das Design und Interaktionsprinzipien können als Inspiration dienen.

  3. ViewModel (VM): In WPF bildet das ViewModel die Brücke zwischen der View und dem Model und ist oft eng mit der Benutzeroberfläche (UI) verbunden durch Mechanismen wie Datenbindung und Commands. In Blazor wird die UI-Logik oft direkt in den Komponenten (analog zu ViewModels) untergebracht, aber die Art der Interaktion und Datenflusssteuerung unterscheidet sich.

Anpassung für Blazor

  • In Blazor kann das ViewModel-Konzept in gewisser Weise beibehalten werden, besonders wenn du Blazor Server verwendest, wo der Zustand serverseitig verwaltet wird. Hier könnten die ViewModel-Klassen als Datenmodell-Handler innerhalb der Blazor-Komponenten dienen.
  • Für Blazor WebAssembly, wo der gesamte Code clientseitig ausgeführt wird, ist es möglich, die ViewModel-Logik direkt in die Blazor-Komponenten zu integrieren, wobei eventuell Anpassungen notwendig sind, um dem asynchronen und event-getriebenen Charakter von Web-Apps Rechnung zu tragen.

Praktische Tipps

  • Abstraktion und Dienste: Um eine hohe Wiederverwendbarkeit zwischen WPF und Blazor zu erreichen, empfiehlt es sich, Geschäftslogik und datenbezogene Funktionen in Diensten oder Bibliotheken zu kapseln, die von beiden Technologien genutzt werden können. Beispiele dafür sind Validierungslogik, Geschäftsregeln und Datenzugriffscodes.
  • API-basierte Architektur: Eine weitere Möglichkeit ist die Nutzung einer API-basierten Architektur, wo das Backend unabhängig von der Frontend-Technologie agiert. Hier könnten sowohl WPF als auch Blazor als Clients fungieren, die über HTTP/REST mit dem Backend kommunizieren.

Gestaltung einer modernen, skalierbaren und sicheren Anwendung

Der Ansatz, eine API-basierte Architektur zu verwenden, ist zukunftsorientiert und kann die Wiederverwendbarkeit zwischen verschiedenen Frontends wie WPF und Blazor maximieren. Durch das klare Trennen von Zuständigkeiten und das Implementieren von Sicherheitsbest Practices kannst du sowohl die Flexibilität deiner Anwendung erhöhen als auch potenzielle Sicherheitsrisiken minimieren.

1. Schichtentrennung in WPF für spätere Wiederverwendbarkeit

In einer WPF-Anwendung, die für spätere Wiederverwendbarkeit in einer API-basierten Architektur entworfen wird, ist es sinnvoll, die Interaktion zwischen der View und dem ViewModel klar und sauber zu gestalten. Statt direkt über HTTP/REST zu kommunizieren, was in WPF nicht üblich ist, kannst du folgendes tun:

  • Datenbindung und Commands: Nutze weiterhin das MVVM-Muster mit starkem Einsatz von Datenbindung und Commands. Dies hilft, die UI-Logik (View) von der Geschäftslogik (ViewModel) zu trennen.

  • Dienste und Repository-Schicht: Führe eine klare Trennung durch die Einführung einer Dienstschicht oder eines Repository-Patterns ein. Diese Schicht wäre verantwortlich für die Kommunikation mit externen APIs oder Datenquellen. Das ViewModel spricht nur mit dieser Schicht und weiß nichts über die tatsächliche Datenquelle (z.B. direkte Datenbankzugriffe oder API-Aufrufe).

  • Interfaces für Dienste: Definiere Interfaces für deine Dienste, sodass die Implementierung leicht ausgetauscht oder gemockt werden kann. Dies fördert die Wiederverwendbarkeit und erleichtert das Testen.

2. Bedenken bei Blazor WebAssembly

Eignung von Blazor WebAssembly: Blazor WebAssembly eignet sich besonders gut für Anwendungen, die offline funktionieren müssen oder eine geringe Latenz zwischen Benutzerinteraktionen und Antwort benötigen. Es ist jedoch richtig, dass alle Geschäftslogiken und Daten clientseitig verarbeitet und gespeichert werden, was Sicherheitsüberlegungen aufwirft.

  • Sicherheitsbedenken: In Bezug auf die Sicherheit ist es wichtig, dass keine sensiblen Daten oder Geschäftslogiken, die geheim gehalten werden müssen, im clientseitigen Code enthalten sind. Alles, was in WebAssembly läuft, kann potenziell von einem Benutzer eingesehen oder modifiziert werden.

  • Serverseitige Validierung: Selbst wenn du Blazor WebAssembly verwendest, sollte die Validierung und Verarbeitung kritischer Daten immer auch auf dem Server stattfinden. Keine kritischen Entscheidungen sollten allein auf der Grundlage von clientseitigem Code getroffen werden.

  • Blazor Server als Alternative: Wenn Sicherheit ein großes Anliegen ist, könnte Blazor Server eine bessere Option sein. Hierbei wird der Code serverseitig ausgeführt, und nur UI-Updates werden über eine SignalR-Verbindung an den Client gesendet. Dies minimiert das Risiko einer Manipulation durch den Endbenutzer.

Ein hybrider Ansatz

Die Kombination von Blazor WebAssembly (WASM) und Blazor Server (SignalR-Verbindung) in einem einzigen Projekt und kann in Szenarien, wo du die Vorteile beider Plattformen nutzen möchtest, durchaus sinnvoll sein und eine leistungsfähige Lösung bieten. Sie erfordert jedoch eine sorgfältige Planung und Architekturgestaltung, um sicherzustellen, dass die Anwendung effizient, sicher und wartbar bleibt. Bei richtigem Design kann dieser hybride Ansatz eine ausgezeichnete Benutzererfahrung bieten, ohne dabei Kompromisse bei der Sicherheit zu machen. Dieser hybride Ansatz kann die Vorteile beider Modelle nutzen: Die Client-seitige Schnelligkeit und Offline-Fähigkeit von Blazor WASM sowie die Server-seitige Sicherheit und Rechenleistung von Blazor Server.

Vorteile der Kombination

  1. Leistung und Benutzererfahrung: Blazor WASM kann eine schnelle Reaktionszeit für Benutzeroberflächeninteraktionen bieten, da der Code direkt im Browser des Benutzers ausgeführt wird. Für Aktionen, die keine sensiblen Daten oder komplexe Logik erfordern, kann dies ideal sein.

  2. Sicherheit und Datenschutz: Blazor Server kann verwendet werden, um sicherzustellen, dass alle Geschäftslogiken und Datenzugriffe, die sensible Informationen verarbeiten, auf dem Server bleiben. Dies vermindert das Risiko, dass sensible Daten kompromittiert werden.

  3. Offline-Funktionalität: Blazor WASM bietet die Möglichkeit, Anwendungen offline verfügbar zu machen, indem die notwendigen Ressourcen und Assets im Browser gecached werden. Dies ist mit Blazor Server nicht möglich.

Implementierung eines hybriden Modells

  • Routing und Navigation: Du könntest bestimmte Teile der Anwendung speziell für Blazor WASM und andere für Blazor Server entwickeln. Die Entscheidung, welcher Teil wo läuft, könnte basierend auf den Sicherheitsanforderungen, der Komplexität der Datenverarbeitung und der Benutzerinteraktion getroffen werden.

  • Komponentenbasierte Entwicklung: Blazor erlaubt die Wiederverwendung von Komponenten. Du könntest Komponenten so entwickeln, dass sie entweder clientseitig (WASM) oder serverseitig (Server) genutzt werden können, je nach Anforderung.

  • APIs als Brücke: Unabhängig davon, ob die Komponente auf dem Client oder Server läuft, können beide Teile über API-Aufrufe miteinander kommunizieren. Dies erlaubt es, dass der Blazor Server als Backend für Blazor WASM agiert, und umgekehrt können bestimmte leichtgewichtige Prozesse an den Client delegiert werden.

Herausforderungen

  • Komplexität in der Entwicklung und Wartung: Die Verwaltung einer Anwendung, die sowohl Blazor WASM als auch Blazor Server umfasst, kann komplex sein. Dies betrifft vor allem das Routing, die Session-Verwaltung und die Konsistenz der Benutzeroberfläche.

  • Performance-Überlegungen: Obwohl Blazor WASM schnelle Client-seitige Interaktionen ermöglicht, müssen die Initialladezeiten und der Ressourcenbedarf sorgfältig optimiert werden, da der gesamte .NET-Runtime und die Anwendungscode im Browser geladen werden müssen.

  • Sicherheitsaspekte: Die Sicherheit der Daten und der Geschäftslogik muss sorgfältig geplant werden, um zu vermeiden, dass sensible Informationen im Client-Teil der Anwendung exponiert werden.

Dienste- und Repository-Schicht

In der Entwicklung von Blazor Server-Anwendungen ist die sorgfältige Unterscheidung zwischen Dienst- und Repository-Schichten von entscheidender Bedeutung. Diese Architekturstrategie unterstützt nicht nur eine klare Trennung der Zuständigkeiten — ein Konzept, bekannt als "Separation of Concerns" — sondern fördert auch die Wiederverwendbarkeit und die Testbarkeit der Anwendung. Indem Dienste und Repositories von den Benutzeroberflächenkomponenten, wie den Blazor-Komponenten, getrennt werden, lässt sich der Code leichter warten und auf andere Plattformen wie Blazor WebAssembly oder sogar auf Nicht-Blazor-Anwendungen übertragen.

Die Repository-Schicht verantwortet die Datenzugriffslogik und fungiert somit als Brücke zur Datenquelle, während die Diensteschicht eine abstraktere Logikschicht darstellt, die Geschäftsregeln und Anwendungslogik verwaltet. Diese Schichtenhierarchie ermöglicht es, dass jede Schicht sich auf ihre spezifischen Aufgaben konzentrieren kann, was die Wartbarkeit, Skalierbarkeit und Testbarkeit des Systems verbessert.

Dienstschicht (Services Layer)

Die Dienstschicht fungiert als Mittler zwischen der Präsentationsschicht (den Blazor-Komponenten) und der Datenzugriffsschicht (Repository). Dienste können Geschäftslogik, Validierungen und komplexe Operationen kapseln, die nicht direkt in die UI-Komponenten oder das Repository gehören.

Verantwortlichkeiten der Dienstschicht:

  • Durchführen von Geschäftslogik, die möglicherweise über das einfache Abrufen oder Speichern von Daten hinausgeht.
  • Validierung von eingehenden Daten und Durchführung von Geschäftsregeln.
  • Koordination von Transaktionen, die mehrere Datenquellen oder Aktionen umfassen können.
  • Abstraktion der Datenzugriffslogik, so dass die Komponenten nur mit den Diensten und nicht direkt mit dem Repository interagieren.
  • Zweck: Die Dienste-Schicht befindet sich über der Repository-Schicht und nutzt diese, um die benötigten Datenoperationen durchzuführen. Diese Schicht fügt eine zusätzliche Logikebene hinzu, die Geschäftsregeln, Berechnungen und Datenverarbeitungen beinhaltet, die spezifisch für die Anwendungslogik sind.
  • Verantwortlichkeiten: In dieser Schicht werden Daten aus den Repositories genommen und gemäß den Geschäftsregeln verarbeitet. Die Dienste-Schicht kann Transaktionen koordinieren, komplexe Geschäftsprozesse abwickeln, Validierungen durchführen und die Daten in einer Form zusammenstellen, die direkt von den Endnutzer-Schnittstellen verwendet werden kann.

Repository-Schicht (Repository Layer)

Das Repository ist verantwortlich für die direkte Interaktion mit der Datenquelle (z.B. Datenbanken, externe APIs, Dateisysteme). Es bietet eine abstrahierte Schnittstelle zum Abrufen und Speichern von Daten, sodass die darüber liegenden Schichten sich nicht um die spezifischen Details der Datenpersistenz kümmern müssen.

Verantwortlichkeiten der Repository-Schicht:

  • Kapselung aller Operationen, die direkt mit der Datenquelle interagieren.
  • Bereitstellung von Methoden zum Abrufen, Hinzufügen, Aktualisieren und Löschen von Daten.
  • Sicherstellung, dass die Datenzugriffslogik von der Business-Logik getrennt ist, was die Wartung und das Testen erleichtert.
  • Zweck: Die Repository-Schicht dient als Abstraktionsebene über der Datenquelle (wie einer Datenbank oder einem externen Web-Service). Ihr Hauptzweck ist es, die Datenzugriffslogik zu kapseln, sodass die Art und Weise, wie Daten abgerufen, gespeichert oder manipuliert werden, von den anderen Teilen der Anwendung isoliert ist.
  • Verantwortlichkeiten: Sie umfasst die Implementierung von CRUD-Operationen (Create, Read, Update, Delete) und sorgt dafür, dass die Interaktionen mit der Datenquelle konsistent und optimiert sind.

Beziehung und Interaktion

  • Datenfluss: Die Daten fließen von der Datenquelle durch das Repository zur Dienste-Schicht und von dort aus weiter zu den Nutzerschnittstellen (zum Beispiel einer Web- oder Desktop-Oberfläche).
  • Abhängigkeit: Die Dienste-Schicht ist abhängig von der Repository-Schicht, da sie die von den Repositories bereitgestellten Daten benötigt, um ihre Funktionen auszuführen. Umgekehrt sollten die Repositories keine Kenntnis von den spezifischen Geschäftsregeln oder der weiteren Datenverarbeitung haben, die in den Diensten stattfindet.

Beispiel

Stellen Sie sich vor, Sie entwickeln eine Anwendung zur Verwaltung von Kundenbeziehungen. Die Repository-Schicht würde die direkte Kommunikation mit der Datenbank handhaben, um Kundendaten zu lesen und zu schreiben. Die Dienste-Schicht würde Funktionen wie Kreditwürdigkeitsprüfungen, die Anwendung von Rabattregeln oder das Senden von Benachrichtigungen an Kunden implementieren, indem sie Daten aus dem Kundenrepository verwendet und weiterverarbeitet.

Integration in Blazor Server

In Blazor Server werden die Dienste und Repositories typischerweise über Dependency Injection (DI) in die Komponenten eingefügt. Blazor unterstützt DI nativ, was die Einrichtung und Verwendung von Diensten und Repositories vereinfacht.

Beispiel zur Einrichtung:

  1. Definieren von Interfaces für Dienste und Repositories: Dies fördert die lose Kopplung und erleichtert das Testen durch Mocking.

  2. Implementieren der Dienste und Repositories: Schreibe konkrete Implementierungen für die definierten Interfaces.

  3. Registrieren der Dienste und Repositories im DI-Container: In Blazor erfolgt dies in der Startup.cs oder Program.cs, abhängig von der Blazor-Version und Konfiguration.

    public void ConfigureServices(IServiceCollection services) {
        services.AddScoped<IMyService, MyService>();
        services.AddScoped<IMyRepository, MyRepository>();
    }
  4. Injizieren und Verwenden in Komponenten: Die Dienste und Repositories können dann in jeder Blazor-Komponente verwendet werden, indem sie über den Konstruktor oder direkt in den Komponenten-Code injiziert werden.

    @inject IMyService myService
    @code {
        protected override async Task OnInitializedAsync() {
            var data = await myService.GetDataAsync();
        }
    }

Services-/Repository Layer, in einer WPF-Anwendung ohne HTTP/REST am Beispiel

Durch dieses Design kannst du die Kundendatenverwaltung und die Kreditwürdigkeitsprüfung in einer WPF-Anwendung klar strukturieren, wobei das Modell sauber von der Darstellung getrennt ist:

  • Repository und Service sind Teil des Models in MVVM und stellen Daten und Logik bereit.
  • ViewModel konsumiert diese Dienste und bereitet Daten für die View auf, ohne dass HTTP/REST involviert sind.
  • View bindet sich an das ViewModel, um die Daten darzustellen und Benutzerinteraktionen zu verarbeiten.

Aufbau der MVVM-Architektur

In der MVVM-Architektur besteht eine klare Trennung zwischen dem Model, der View und dem ViewModel:

  • Model: Das Model in MVVM repräsentiert die Datenzugriffslogik und Geschäftslogik. Es ist direkt verantwortlich für den Umgang mit den Daten der Anwendung. Dies schließt die Kommunikation mit Datenbanken, das Verarbeiten von Geschäftsregeln und die Validierung ein. Services Layer und Repository Layer sind oft Teil des Models oder werden eng mit ihm assoziiert.
  • ViewModel: Das ViewModel agiert als Bindeglied zwischen der View und dem Model. Es verarbeitet Daten vom Model, um sie in einer für die View geeigneten Form darzustellen. Es reagiert auf Commands und steuert die Logik der Benutzeroberfläche, ohne dass das ViewModel direkt mit der View interagiert.
  • View: Die View ist für die Darstellung der Benutzeroberfläche zuständig und verwendet Datenbindung, um interaktiv Daten vom ViewModel anzuzeigen und Änderungen an das ViewModel zurückzugeben.

Beispiel: Kundendaten und Kreditwürdigkeitsprüfungen in WPF

1. Strukturierung von Repository und Service

  • Repository Layer: Verantwortlich für den direkten Datenzugriff. Zum Beispiel könnte ein CustomerRepository Methoden wie GetCustomer(int id) und SaveCustomer(Customer customer) enthalten.
  • Service Layer: Bietet eine höhere Ebene der Datenverarbeitung. Ein CreditService könnte Methoden wie CheckCreditworthiness(Customer customer) anbieten, die Geschäftslogik zur Bewertung der Kreditwürdigkeit eines Kunden beinhalten.

2. Einrichten der ViewModel und Verwendung in WPF

  • CustomerViewModel: Das ViewModel könnte Eigenschaften wie CustomerName, CreditScore und Commands wie SaveCommand und CheckCreditCommand enthalten.

Beispielcode für ein einfaches Setup

public class CustomerViewModel : INotifyPropertyChanged {
    private readonly ICustomerRepository _customerRepository;
    private readonly ICreditService _creditService;

    public CustomerViewModel(ICustomerRepository customerRepository, ICreditService creditService) {
        _customerRepository = customerRepository;
        _creditService = creditService;
    }
    public string CustomerName { get; set; }
    public int CreditScore { get; private set; }
    // Command zum Laden eines Kunden
    public ICommand LoadCustomerCommand => new RelayCommand(LoadCustomer);
    private void LoadCustomer() {
        var customer = _customerRepository.GetCustomer(1);
        CustomerName = customer.Name;
        OnPropertyChanged(nameof(CustomerName));
    }
    // Command zur Prüfung der Kreditwürdigkeit
    public ICommand CheckCreditCommand => new RelayCommand(CheckCredit);
    private void CheckCredit() {
        var customer = new Customer { Name = CustomerName };
        CreditScore = _creditService.CheckCreditworthiness(customer);
        OnPropertyChanged(nameof(CreditScore));
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Web-App-Architektur mit HTTP/REST am Beispiel

In der Web-App-Architektur verlagert sich der Fokus auf die Interaktion über das Netzwerk, wobei die Client-Anwendung RESTful-Webdienste konsumiert, die von einem Server bereitgestellt werden. Durch die klare Trennung zwischen Backend-Logik (Server) und Frontend-Presentation (Client) mittels REST APIs wird die Anwendung skalierbarer, wartbarer und besser organisierbar.

Um die Beispiele für die Verwaltung von Kundendaten und Kreditwürdigkeitsprüfungen in einer Web-App unter Verwendung von HTTP/REST zu implementieren, betrachten wir eine typische moderne Web-Anwendung, die auf einer Client-Server-Architektur basiert. Hier würde die Kommunikation zwischen dem Client (beispielsweise eine Blazor-WebAssembly oder eine andere SPA) und dem Server über HTTP/RESTful-APIs erfolgen.

Schritte zur Implementierung in einer Web-App:

1. Backend-Setup (Server-Seite)

a. Erstellung der REST API:

  • Kundendaten-APIs: Erstelle Endpunkte, die CRUD-Operationen (Create, Read, Update, Delete) für Kundendaten ermöglichen.
  • Kreditwürdigkeitsprüfungs-API: Entwickle einen speziellen Endpunkt, der die Kreditwürdigkeit eines Kunden basierend auf übermittelten Daten prüft.

b. Technologien und Frameworks:

  • Verwende ASP.NET Core für die Erstellung der API, da es robuste Unterstützung für die Entwicklung von RESTful-Webdiensten bietet.
  • Nutze Entity Framework Core für die Datenzugriffsschicht, um die Kommunikation mit der Datenbank zu verwalten.

Beispielcode für den Controller in ASP.NET Core:

[ApiController]
[Route("api/customers")]
public class CustomersController : ControllerBase {
    private readonly ICustomerRepository _customerRepository;
    private readonly ICreditService _creditService;
    public CustomersController(ICustomerRepository customerRepository, ICreditService creditService) {
        _customerRepository = customerRepository;
        _creditService = creditService;
    }
    [HttpGet("{id}")] public ActionResult<CustomerDto> GetCustomer(int id) {
        var customer = _customerRepository.GetCustomer(id);
        if (customer == null) return NotFound();
        return Ok(customer);
    }
    [HttpPost] public ActionResult SaveCustomer(CustomerDto customerDto)
    {
        var customer = new Customer { Name = customerDto.Name };
        _customerRepository.SaveCustomer(customer);
        return Ok();
    }
    [HttpGet("check-credit/{id}")] public ActionResult<int> CheckCredit(int id) {
        var customer = _customerRepository.GetCustomer(id);
        if (customer == null) return NotFound();
        var creditScore = _creditService.CheckCreditworthiness(customer);
        return Ok(creditScore);
    }
}

2. Frontend-Setup (Client-Seite)

a. Konsumieren der API:

  • Verwende HTTP-Clients wie HttpClient in Blazor WebAssembly, um Requests an die Server-APIs zu senden.
  • Implementiere entsprechende UI-Komponenten, die Daten anzeigen und Aktionen wie das Laden von Kundeninformationen oder die Überprüfung der Kreditwürdigkeit auslösen können.

b. Beispiel für eine Blazor-Komponente:

@page "/customer/{Id}"
@inject HttpClient Http
<h3>Kundeninformation</h3>
<div>Name: @customer.Name</div>
<div>Kreditscore: @creditScore</div>
<button @onclick="LoadCustomer">Kunden laden</button>
<button @onclick="CheckCredit">Kreditwürdigkeit prüfen</button>
@code {
    [Parameter] public string Id { get; set; }
    private Customer customer;
    private int creditScore;
    protected override async Task OnInitializedAsync() {
        await LoadCustomer();
    }
    private async Task LoadCustomer() {
        customer = await Http.GetJsonAsync<Customer>($"api/customers/{Id}");
    }
    private async Task CheckCredit() {
        creditScore = await Http.GetJsonAsync<int>($"api/customers/check-credit/{Id}");
    }
}

( With ♥ by C# XAML Csharp GPT and me. )

Zusammenfassung "WPF und Blazor" mit Fokus auf Blazor in .NET 8

Die Integration von Blazor in .NET 8 eröffnet neue Möglichkeiten für die Wiederverwendung von Code zwischen WPF und Blazor durch den Einsatz von Diensten und einer API-zentrierten Architektur, die sowohl moderne Sicherheitspraktiken als auch eine skalierbare Anwendungsgestaltung unterstützt.

Dies ist eine Zusammenfassung des Artikels Shared Code für WPF-Anwendung und Blazor-Anwendung mit Fokus auf Blazor in .NET 8.

Einleitung

Die gemeinsame Nutzung von Code zwischen WPF und Blazor in .NET 8 stellt eine Herausforderung dar, da beide Plattformen spezifische Best Practices und Architekturen aufweisen. Der Schlüssel zur Maximierung der Wiederverwendbarkeit liegt in der klugen Abstraktion und Trennung der Geschäftslogik von der UI-spezifischen Logik.

Strukturelle Überlegungen

Model

Das Model sollte technologieunabhängig gestaltet werden, um in beiden Umgebungen (WPF und Blazor) verwendet werden zu können. Eine solche Gestaltung fördert die Wiederverwendbarkeit des Codes ohne plattformspezifische Abhängigkeiten.

View

Die Views bleiben plattformspezifisch: WPF nutzt XAML und Blazor verwendet Razor Templates oder HTML/CSS. Direkte Wiederverwendung ist hier nicht möglich, jedoch können Designprinzipien übertragen werden.

ViewModel

Für Blazor kann das ViewModel-Konzept adaptiert werden. Insbesondere in Blazor Server-Szenarien können ViewModel-Klassen als Datenmodell-Handler innerhalb der Komponenten dienen, während bei Blazor WebAssembly eine Integration der ViewModel-Logik in die Komponenten erforderlich ist.

Praktische Tipps zur Wiederverwendung von Code

  • Abstraktion und Dienste: Durch Kapselung der Geschäftslogik und datenbezogenen Funktionen in Diensten, die sowohl von WPF als auch von Blazor genutzt werden können, lässt sich die Wiederverwendbarkeit erhöhen.
  • API-basierte Architektur: Eine API-basierte Architektur, bei der das Backend unabhängig von der Frontend-Technologie agiert, ermöglicht es, dass WPF und Blazor als Clients fungieren.

Gestaltung einer modernen, skalierbaren und sicheren Anwendung

Die Nutzung einer API-basierten Architektur ist zukunftsweisend und fördert die Wiederverwendbarkeit zwischen verschiedenen Frontends. Dies erfordert eine klare Trennung von Zuständigkeiten und die Implementierung von Sicherheitsbest Practices.

Hybrider Ansatz: Blazor WebAssembly und Blazor Server

Die Kombination aus Blazor WebAssembly und Blazor Server in einem Projekt bietet Vorteile hinsichtlich Leistung, Sicherheit und Offline-Funktionalität. Sie erfordert jedoch eine sorgfältige Planung und Architekturgestaltung.

  • Vorteile der Kombination: Schnelle Client-seitige Interaktionen mit Blazor WASM und erhöhte Sicherheit durch serverseitige Verarbeitung mit Blazor Server.
  • Herausforderungen: Die Komplexität in der Entwicklung und Wartung sowie Sicherheitsaspekte müssen sorgfältig geplant werden.

Dienste- und Repository-Schicht

Die klare Unterscheidung zwischen Dienst- und Repository-Schichten ist entscheidend für die Wiederverwendbarkeit und Testbarkeit der Anwendung. In Blazor Server werden diese Schichten typischerweise über Dependency Injection in die Komponenten eingebunden.

Implementierung eines hybriden Modells

  • Routing und Navigation: Bestimmte Anwendungsteile können speziell für Blazor WASM oder für Blazor Server entwickelt werden, basierend auf Sicherheitsanforderungen und Komplexität der Datenverarbeitung.
  • Komponentenbasierte Entwicklung: Entwickle Komponenten, die je nach Anforderung clientseitig oder serverseitig genutzt werden können.

( With ♥ by Blazor .net 8 and me. )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment