Fehlerbehandlung, Logging und feldbezogene Validierung (Kapitel 13.2)
Zentrale Exception-Behandlung (Dispatcher.UIThread.UnhandledException, AppDomain, TaskScheduler) verhindert Abstürze und protokolliert Fehler über AppLogger in eine rotierende Log-Datei im App-Datenverzeichnis. Toast-Benachrichtigungen zeigen Erfolg/Fehler global an. Alle Dialoge mit Formularfeldern zeigen Validierungsmeldungen jetzt direkt am betroffenen Feld statt in einem Sammel-Label. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using Avalonia.Threading;
|
||||
using LehrerApp.Core.Services;
|
||||
|
||||
namespace LehrerApp.Desktop.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Zentrale Exception-Behandlung (13.2.1): protokolliert jeden unerwarteten Fehler und zeigt
|
||||
/// eine verständliche Meldung statt eines rohen Absturzes.
|
||||
///
|
||||
/// Reichweite ehrlich betrachtet: <see cref="Dispatcher"/>.UIThread.UnhandledException kann
|
||||
/// Ausnahmen aus Befehlen/Ereignis-Handlern auf dem UI-Thread abfangen und die App am Leben
|
||||
/// erhalten (Handled = true) — das deckt den weit überwiegenden Teil realer Abstürze in einer
|
||||
/// Desktop-App ab. AppDomain.UnhandledException und TaskScheduler.UnobservedTaskException sind
|
||||
/// Sicherheitsnetze für Fehler außerhalb des UI-Threads; die App kann eine "IsTerminating"-
|
||||
/// Ausnahme dort nicht mehr verhindern, aber wenigstens vollständig protokollieren, bevor sie endet.
|
||||
/// </summary>
|
||||
public static class GlobalExceptionHandler
|
||||
{
|
||||
private static AppLogger? _logger;
|
||||
private static NotificationService? _notifications;
|
||||
|
||||
public static void Install(AppLogger logger, NotificationService? notifications = null)
|
||||
{
|
||||
_logger = logger;
|
||||
_notifications = notifications;
|
||||
|
||||
Dispatcher.UIThread.UnhandledException += OnDispatcherUnhandledException;
|
||||
AppDomain.CurrentDomain.UnhandledException += OnAppDomainUnhandledException;
|
||||
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
||||
}
|
||||
|
||||
/// Muss aufgerufen werden, sobald der DI-Container steht, damit spätere Fehler
|
||||
/// (die vor dem Container auftreten könnten) noch als Toast sichtbar werden.
|
||||
public static void AttachNotifications(NotificationService notifications) => _notifications = notifications;
|
||||
|
||||
private static void OnDispatcherUnhandledException(object? sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
_logger?.Error("Unbehandelter Fehler auf dem UI-Thread.", e.Exception);
|
||||
_notifications?.ShowError("Es ist ein unerwarteter Fehler aufgetreten. Details wurden protokolliert.");
|
||||
e.Handled = true; // App am Leben halten statt abzustürzen.
|
||||
}
|
||||
|
||||
private static void OnAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
_logger?.Error(
|
||||
$"Unbehandelter Fehler außerhalb des UI-Threads (IsTerminating={e.IsTerminating}).",
|
||||
e.ExceptionObject as Exception);
|
||||
}
|
||||
|
||||
private static void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
|
||||
{
|
||||
_logger?.Error("Unbeobachtete Ausnahme in einem Hintergrund-Task.", e.Exception);
|
||||
e.SetObserved(); // verhindert, dass die Ausnahme unbemerkt verschwindet.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user