diff --git a/App.axaml.cs b/App.axaml.cs index a326d8c..c52d5d7 100644 --- a/App.axaml.cs +++ b/App.axaml.cs @@ -5,8 +5,10 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using AuroraDesk.Presentation.Configuration; +using AuroraDesk.Infrastructure.Configuration; +using AuroraDesk.Infrastructure.Extensions; using AuroraDesk.Presentation.Extensions; +using AuroraDesk.Presentation.ViewModels; using AuroraDesk.Presentation.Views; using ReactiveUI; using Splat; @@ -15,7 +17,7 @@ using System.IO; namespace AuroraDesk; -public partial class App : Application +public partial class App : Avalonia.Application { private IServiceProvider? _serviceProvider; private ILogger? _logger; @@ -31,49 +33,32 @@ public partial class App : Application { AvaloniaXamlLoader.Load(this); - // 注册自定义 ViewLocator(必须在路由系统使用之前注册) - // 执行顺序:ViewLocator 先注册,ServiceProvider 后注册(在 OnFrameworkInitializationCompleted 中) - // ViewLocator 支持回退机制:如果 ServiceProvider 未注册,会使用 Activator.CreateInstance - // 因此先注册 ViewLocator 是安全的,即使此时 ServiceProvider 还未创建 + // 注册自定义 ViewLocator Locator.CurrentMutable.RegisterConstant(new Presentation.Views.ViewLocator(), typeof(IViewLocator)); } public override void OnFrameworkInitializationCompleted() { - // 在框架初始化完成后创建和配置 HostBuilder - // 执行顺序:ViewLocator 已在 Initialize() 中注册,现在创建 HostBuilder 和 ServiceProvider - // 虽然 ViewLocator 可以回退到 Activator.CreateInstance,但注册 ServiceProvider 后 - // ViewLocator 将优先使用依赖注入创建 View,这样可以注入 View 所需的服务 var host = CreateHostBuilder().Build(); _serviceProvider = host.Services; _logger = _serviceProvider.GetRequiredService>(); // 注册 ServiceProvider 到 Splat,以便 ViewLocator 可以使用依赖注入创建 View - // 必须在 MainWindow 创建和路由导航之前注册,因为路由导航会触发 ViewLocator.ResolveView - // 注册后,ViewLocator 将优先使用 DI 容器创建 View 实例 Locator.CurrentMutable.RegisterConstant(_serviceProvider, typeof(IServiceProvider)); - - _logger.LogInformation("App 框架初始化完成,HostBuilder 已创建并配置"); if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - _logger.LogInformation("使用依赖注入创建 MainWindow"); - desktop.MainWindow = _serviceProvider.GetRequiredService(); + var mainWindow = _serviceProvider.GetRequiredService(); + desktop.MainWindow = mainWindow; } base.OnFrameworkInitializationCompleted(); - _logger.LogInformation("框架初始化完成"); } - /// - /// 创建 HostBuilder - /// - /// HostBuilder private IHostBuilder CreateHostBuilder() => Host.CreateDefaultBuilder() .ConfigureAppConfiguration((context, config) => { - // 配置应用程序设置 config.SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true) @@ -81,28 +66,32 @@ public partial class App : Application }) .ConfigureLogging((context, logging) => { - // 配置日志 logging.ClearProviders(); logging.AddConfiguration(context.Configuration.GetSection("Logging")); - // 启用控制台日志以便调试 logging.AddConsole(); logging.AddDebug(); }) .ConfigureServices((context, services) => { - // 注册配置 services.Configure(context.Configuration.GetSection("AppSettings")); - // 注册业务服务 + // 注册服务 services.AddBusinessServices(); - - // 注册 ReactiveUI 服务(必须在注册 ViewModel 之前,因为 ViewModel 依赖 AppViewModel) + services.AddViewModels(); + services.AddNavigationService(); services.AddReactiveUI(); - // 注册 ViewModel(依赖 AppViewModel) - services.AddViewModels(); + // 注册 MainWindowViewModel + services.AddTransient(provider => + provider.GetRequiredService().MainWindowViewModel); - // 注册 Avalonia 应用程序 - services.AddTransient(); + // 注册 MainWindow + services.AddTransient(provider => + { + var loggerFactory = provider.GetRequiredService(); + var logger = loggerFactory.CreateLogger(); + var viewModel = provider.GetRequiredService(); + return new AuroraDesk.Presentation.Views.MainWindow(viewModel, logger); + }); }); } \ No newline at end of file diff --git a/AuroraDesk.csproj b/AuroraDesk.csproj index 8e8cc49..c645488 100644 --- a/AuroraDesk.csproj +++ b/AuroraDesk.csproj @@ -55,5 +55,6 @@ + diff --git a/AuroraDesk.sln b/AuroraDesk.sln index eae89ed..c30d0b0 100644 --- a/AuroraDesk.sln +++ b/AuroraDesk.sln @@ -6,6 +6,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraDesk", "AuroraDesk.cs EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraDesk.Presentation", "..\AuroraDesk.Presentation\AuroraDesk.Presentation.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraDesk.Core", "..\AuroraDesk.Core\AuroraDesk.Core.csproj", "{C3D4E5F6-A7B8-9012-CDEF-123456789012}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraDesk.Application", "..\AuroraDesk.Application\AuroraDesk.Application.csproj", "{D4E5F6A7-B8C9-0123-DEF0-123456789012}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraDesk.Infrastructure", "..\AuroraDesk.Infrastructure\AuroraDesk.Infrastructure.csproj", "{E5F6A7B8-C9D0-1234-EF01-123456789012}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,6 +26,18 @@ Global {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU {B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU + {D4E5F6A7-B8C9-0123-DEF0-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4E5F6A7-B8C9-0123-DEF0-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4E5F6A7-B8C9-0123-DEF0-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4E5F6A7-B8C9-0123-DEF0-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU + {E5F6A7B8-C9D0-1234-EF01-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5F6A7B8-C9D0-1234-EF01-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5F6A7B8-C9D0-1234-EF01-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5F6A7B8-C9D0-1234-EF01-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MainWindow.axaml b/MainWindow.axaml deleted file mode 100644 index 1baa94b..0000000 --- a/MainWindow.axaml +++ /dev/null @@ -1,372 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MainWindow.axaml.cs b/MainWindow.axaml.cs deleted file mode 100644 index bcf72ad..0000000 --- a/MainWindow.axaml.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using Avalonia.Controls; -using Avalonia.Controls.Primitives; -using Avalonia.Input; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; -using Microsoft.Extensions.Logging; -using AuroraDesk.Presentation.ViewModels; -using ReactiveUI; -using System.Reactive.Disposables; - -namespace AuroraDesk; - -public partial class MainWindow : ReactiveWindow, IActivatableView -{ - private readonly ILogger? _logger; - - /// - /// 无参构造函数,用于 XAML 设计器 - /// - public MainWindow() - { - InitializeComponent(); - SetupWindowControls(); - } - - /// - /// 构造函数,接受依赖注入的 ViewModel - /// - /// 主窗口的 ViewModel - /// 日志记录器 - public MainWindow(MainWindowViewModel viewModel, ILogger? logger = null) - { - ArgumentNullException.ThrowIfNull(viewModel); - - _logger = logger; - InitializeComponent(); - ViewModel = viewModel; - SetupWindowControls(); - - _logger?.LogInformation("MainWindow 已创建,ViewModel 已设置"); - - // 使用 WhenActivated 管理订阅 - this.WhenActivated(disposables => - { - // 可以在这里添加窗口级别的订阅,如果需要的话 - // 例如:this.WhenAnyValue(x => x.ViewModel.Title) - // .Subscribe(title => ...) - // .DisposeWith(disposables); - }); - } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - /// - /// 设置窗口控制按钮事件 - /// - private void SetupWindowControls() - { - // 设置标题栏拖动功能 - var titleBarGrid = this.FindControl("TitleBarGrid"); - if (titleBarGrid != null) - { - titleBarGrid.PointerPressed += OnTitleBarPointerPressed; - } - - // 最小化按钮 - var minimizeButton = this.FindControl