using Avalonia; using IBKRTrader.App.Avalonia.Shell; using IBKRTrader.Core.Logging; using IBKRTrader.Core.Modularity; using IBKRTrader.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace IBKRTrader.App.Avalonia; /// /// Einstiegspunkt der plattformneutralen Oberfläche. /// /// Bewusst zweigeteilt: stellt den Host mit Persistenz, /// Diensten und Modulen zusammen – ohne jeden Bezug zur Oberfläche. Erst danach wird Avalonia /// daran gehängt. Derselbe Host trägt den kopflosen Linux-Dienst /// (IBKRTrader.Daemon). /// internal static class Program { [STAThread] public static int Main(string[] args) { // Konstruktionsprüfung aller Fenster ohne Message-Loop und ohne laufende Dienste. if (HasFlag(args, "--smoke-ui")) return SmokeUi.Run(); var modules = AppHostBuilder.CreateModules(); using var host = AppHostBuilder.Build(modules, ShellServices.Register); AppHostBuilder.RunStartupChecks(host.Services); var logger = host.Services.GetRequiredService(); logger.Info("Core", "=== IBKRTrader startet ==="); logger.Info("Core", $"Version: 1.0.0 | .NET {Environment.Version}"); host.Start(); StartModules(modules, logger); try { App.Services = host.Services; BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); return 0; } finally { // Geordnetes Herunterfahren – erst nachdem die Oberfläche beendet ist. StopModules(modules, logger); host.StopAsync(TimeSpan.FromSeconds(30)).GetAwaiter().GetResult(); } } /// Von Avalonia erwartete Fabrikmethode (auch vom XAML-Previewer genutzt). public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .UsePlatformDetect() .WithInterFont() .LogToTrace(); private static void StartModules(IReadOnlyList modules, LoggingService logger) { foreach (var module in modules) { try { module.StartAsync(default).GetAwaiter().GetResult(); } catch (Exception ex) { logger.Error(module.Name, $"{module.Name}: Start fehlgeschlagen.", ex); } } logger.Info("Core", "IBKRTrader bereit."); } private static void StopModules(IReadOnlyList modules, LoggingService logger) { foreach (var module in modules) { try { module.StopAsync(default).GetAwaiter().GetResult(); } catch (Exception ex) { logger.Warn(module.Name, $"{module.Name}: Stopp fehlgeschlagen: {ex.Message}"); } } } private static bool HasFlag(string[] args, string flag) => args.Any(a => string.Equals(a, flag, StringComparison.OrdinalIgnoreCase)); }