# AuroraDesk 项目重构计划 ## 📋 项目概述 **目标项目名**: AuroraDesk **原项目名**: MyAvaloniaApp **目标架构**: 整洁架构 (Clean Architecture) **重点优化**: 减少 ViewModels 耦合,提高代码可维护性 **环境**: Windows 10 **注意事项**: 避免使用 Linux 语法,防止乱码问题 --- ## 🎯 重构目标 ### 1. 项目重命名 - 项目名称:`MyAvaloniaApp` → `AuroraDesk` - 解决方案文件:`MyAvaloniaApp.sln` → `AuroraDesk.sln` - 项目文件:`MyAvaloniaApp.csproj` → `AuroraDesk.csproj` - 命名空间前缀:`MyAvaloniaApp.*` → `AuroraDesk.*` ### 2. 架构重构(整洁架构) #### 2.1 项目分层结构 ``` AuroraDesk/ ├── AuroraDesk.Core/ # 核心领域层 │ ├── Entities/ # 领域实体 │ │ ├── NavigationItem.cs │ │ ├── TabItem.cs │ │ └── ... │ ├── Interfaces/ # 领域接口 │ └── Exceptions/ # 领域异常 │ ├── AuroraDesk.Application/ # 应用层 │ ├── Services/ # 应用服务接口 │ │ ├── INavigationService.cs │ │ ├── IPageFactory.cs │ │ └── ... │ ├── DTOs/ # 数据传输对象 │ └── Mappings/ # 映射配置 │ ├── AuroraDesk.Infrastructure/ # 基础设施层 │ ├── Services/ # 服务实现 │ │ ├── NavigationService.cs │ │ ├── PageFactory.cs │ │ ├── DataService.cs │ │ ├── ApiService.cs │ │ └── ResourceService.cs │ ├── Configuration/ # 配置 │ │ └── AppSettings.cs │ └── Extensions/ # 扩展方法 │ └── ServiceCollectionExtensions.cs │ └── AuroraDesk.Presentation/ # 表示层 ├── ViewModels/ # ViewModels(精简) │ ├── MainWindowViewModel.cs │ ├── AppViewModel.cs │ └── Base/ │ └── RoutableViewModel.cs ├── Views/ # Views │ ├── ViewLocator.cs │ └── Pages/ ├── Converters/ # 转换器 └── Behaviors/ # 行为 ``` #### 2.2 命名空间规划 ```csharp // 核心领域层 AuroraDesk.Core AuroraDesk.Core.Entities AuroraDesk.Core.Interfaces AuroraDesk.Core.Exceptions // 应用层 AuroraDesk.Application AuroraDesk.Application.Services AuroraDesk.Application.DTOs AuroraDesk.Application.Mappings // 基础设施层 AuroraDesk.Infrastructure AuroraDesk.Infrastructure.Services AuroraDesk.Infrastructure.Configuration AuroraDesk.Infrastructure.Extensions // 表示层 AuroraDesk.Presentation AuroraDesk.Presentation.ViewModels AuroraDesk.Presentation.ViewModels.Base AuroraDesk.Presentation.Views AuroraDesk.Presentation.Views.Pages AuroraDesk.Presentation.Converters AuroraDesk.Presentation.Behaviors ``` ### 3. 解耦 ViewModels 策略 #### 3.1 问题分析 **当前问题**: - `MainWindowViewModel` 中直接创建了所有 `PageViewModel` 实例(高耦合) - ViewModel 创建逻辑分散在 `InitializeNavigationItems` 方法中 - 难以进行单元测试 - 违反单一职责原则 **解决方案**: 1. **引入 PageViewModel 工厂模式** - 创建 `IPageViewModelFactory` 接口 - 实现 `PageViewModelFactory` 类 - 通过依赖注入管理 ViewModel 创建 2. **引入导航服务** - 创建 `INavigationService` 接口 - 封装导航逻辑,减少 MainWindowViewModel 职责 - 统一管理导航项配置 3. **将配置数据外置** - 创建导航配置数据类(NavigationConfig) - 从 ViewModel 中分离配置数据 - 配置可在应用启动时注入 #### 3.2 重构后的依赖关系 ``` MainWindowViewModel ↓ (依赖) INavigationService // 处理导航逻辑 IPageViewModelFactory // 创建 PageViewModel ILogger // 日志记录 IScreen // ReactiveUI 路由 不再直接依赖: ❌ DashboardPageViewModel ❌ UsersPageViewModel ❌ SettingsPageViewModel ... (所有具体的 PageViewModel) ``` --- ## 📝 详细重构步骤 ### 阶段一:准备工作(不修改代码) #### 步骤 1.1: 创建新项目结构(可选,建议先单项目重构) - [ ] 创建分层项目结构(或多文件夹结构) - [ ] 规划文件迁移路径 - [ ] 备份当前代码 #### 步骤 1.2: 分析依赖关系 - [ ] 梳理所有 ViewModel 之间的依赖 - [ ] 识别所有直接 new 实例化的地方 - [ ] 记录需要注入的服务 --- ### 阶段二:架构重构(按顺序执行) #### 步骤 2.1: 创建核心领域层 - [ ] 创建 `AuroraDesk.Core` 项目/文件夹 - [ ] 迁移实体类:`NavigationItem`, `TabItem` 到 `Core.Entities` - [ ] 更新命名空间:`AuroraDesk.Core.Entities` - [ ] 移除业务逻辑,只保留数据模型 #### 步骤 2.2: 创建应用层接口 - [ ] 创建 `AuroraDesk.Application` 项目/文件夹 - [ ] 定义 `INavigationService` 接口 - [ ] 定义 `IPageViewModelFactory` 接口 - [ ] 定义导航配置 DTO(NavigationConfig) #### 步骤 2.3: 创建基础设施层实现 - [ ] 创建 `AuroraDesk.Infrastructure` 项目/文件夹 - [ ] 实现 `NavigationService` - [ ] 实现 `PageViewModelFactory` - [ ] 迁移现有服务:`DataService`, `ApiService`, `ResourceService` - [ ] 更新服务命名空间为 `AuroraDesk.Infrastructure.Services` #### 步骤 2.4: 重构表示层 - [ ] 更新 `MainWindowViewModel`,移除直接创建 ViewModel 的代码 - [ ] 注入 `INavigationService` 和 `IPageViewModelFactory` - [ ] 简化 `MainWindowViewModel` 的职责 - [ ] 更新所有命名空间为 `AuroraDesk.Presentation.*` --- ### 阶段三:项目重命名(谨慎执行) #### 步骤 3.1: 重命名项目文件 - [ ] 重命名 `.csproj` 文件 - [ ] 重命名 `.sln` 文件 - [ ] 更新项目文件中的 `` 和 `` #### 步骤 3.2: 重命名命名空间(逐个文件修改) - [ ] **不要使用批量替换** - [ ] 逐个文件修改命名空间声明 - [ ] 逐个文件更新 using 语句 - [ ] 每次修改后编译测试 #### 步骤 3.3: 更新配置文件 - [ ] 更新 `appsettings.json` 中的项目相关配置 - [ ] 更新 `app.manifest` 中的程序集名称 - [ ] 更新所有批处理文件和脚本 --- ### 阶段四:解耦 ViewModels(重点) #### 步骤 4.1: 创建工厂接口和实现 ```csharp // AuroraDesk.Application/Services/IPageViewModelFactory.cs public interface IPageViewModelFactory { T CreatePageViewModel(IScreen screen) where T : IRoutableViewModel; IRoutableViewModel CreatePageViewModel(string pageId, IScreen screen); } ``` #### 步骤 4.2: 实现工厂类 ```csharp // AuroraDesk.Infrastructure/Services/PageViewModelFactory.cs public class PageViewModelFactory : IPageViewModelFactory { private readonly IServiceProvider _serviceProvider; public IRoutableViewModel CreatePageViewModel(string pageId, IScreen screen) { return pageId switch { "dashboard" => _serviceProvider.GetRequiredService(), "users" => _serviceProvider.GetRequiredService(), // ... 其他页面 _ => throw new ArgumentException($"Unknown page: {pageId}") }; } } ``` #### 步骤 4.3: 创建导航服务 ```csharp // AuroraDesk.Application/Services/INavigationService.cs public interface INavigationService { ObservableCollection GetNavigationItems(); void NavigateToPage(NavigationItem item); } ``` #### 步骤 4.4: 重构 MainWindowViewModel - [ ] 移除 `InitializeNavigationItems` 方法中的 ViewModel 创建逻辑 - [ ] 注入 `INavigationService` 获取导航项 - [ ] 使用 `IPageViewModelFactory` 创建 ViewModel - [ ] 简化导航逻辑,委托给 `INavigationService` --- ### 阶段五:注册依赖注入 #### 步骤 5.1: 更新 ServiceCollectionExtensions - [ ] 注册 `IPageViewModelFactory` → `PageViewModelFactory` - [ ] 注册 `INavigationService` → `NavigationService` - [ ] 注册所有 PageViewModel 为 Transient(或 Scoped) - [ ] 更新命名空间引用 #### 步骤 5.2: 更新 App.axaml.cs - [ ] 确保所有新服务正确注册 - [ ] 更新 ViewLocator 的命名空间 - [ ] 测试依赖注入是否正常工作 --- ### 阶段六:测试和验证 #### 步骤 6.1: 编译测试 - [ ] 清理解决方案并重新编译 - [ ] 修复所有编译错误 - [ ] 修复所有命名空间引用错误 #### 步骤 6.2: 运行时测试 - [ ] 启动应用程序 - [ ] 测试导航功能 - [ ] 测试所有页面能否正常加载 - [ ] 测试标签页功能 #### 步骤 6.3: 代码检查 - [ ] 检查是否还有直接 new ViewModel 的地方 - [ ] 检查命名空间是否全部更新 - [ ] 检查是否有循环依赖 --- ## 🔧 技术实现细节 ### 1. PageViewModel 注册方式 ```csharp // ServiceCollectionExtensions.cs services.AddTransient(); services.AddTransient(); services.AddTransient(); // ... 其他 PageViewModel ``` ### 2. 导航配置数据 ```csharp // NavigationConfig.cs public class NavigationConfig { public List Items { get; set; } = new(); } public class NavigationItemConfig { public string Id { get; set; } = string.Empty; public string Title { get; set; } = string.Empty; public string PageViewModelType { get; set; } = string.Empty; public IconType IconType { get; set; } public List? Children { get; set; } } ``` ### 3. MainWindowViewModel 重构示例 **重构前**: ```csharp private void InitializeNavigationItems() { _navigationItems = new ObservableCollection { new NavigationItem { ViewModel = new DashboardPageViewModel(_screen) }, new NavigationItem { ViewModel = new UsersPageViewModel(_screen) }, // ... }; } ``` **重构后**: ```csharp private readonly INavigationService _navigationService; public MainWindowViewModel( IScreen screen, INavigationService navigationService, ILogger? logger = null) { _screen = screen; _navigationService = navigationService; _logger = logger; NavigationItems = _navigationService.GetNavigationItems(); } ``` --- ## ⚠️ 注意事项 ### 1. 不要批量替换 - ❌ **禁止**:使用 Visual Studio 的全局查找替换功能批量替换命名空间 - ✅ **正确做法**:逐个文件修改,每次修改后编译测试 ### 2. Windows 10 环境 - ❌ **避免**:使用 Linux 风格的路径分隔符或命令 - ✅ **使用**:Windows 路径分隔符 `\` 或使用 `Path.Combine` - ✅ **使用**:PowerShell 脚本而非 Bash 脚本 ### 3. 编译顺序 - 先编译被依赖的层(Core → Application → Infrastructure → Presentation) - 每次修改一层后立即编译测试 ### 4. Git 版本控制 - 每个阶段完成后提交一次代码 - 使用有意义的提交信息 - 如果出现问题可以回退到上一个阶段 --- ## 📊 预期成果 ### 代码质量提升 - ✅ ViewModels 耦合度降低 80%+ - ✅ 代码可测试性提升 - ✅ 符合整洁架构原则 - ✅ 易于扩展新功能 ### 项目结构 - ✅ 清晰的分层架构 - ✅ 统一的命名空间规范(Aurora 前缀) - ✅ 更好的代码组织 ### 维护性 - ✅ 新页面添加只需注册,无需修改 MainWindowViewModel - ✅ 导航逻辑集中管理 - ✅ 配置与代码分离 --- ## 📅 执行时间估算 - **阶段一**(准备):0.5 天 - **阶段二**(架构重构):2-3 天 - **阶段三**(重命名):1-2 天 - **阶段四**(解耦):2-3 天 - **阶段五**(DI注册):0.5 天 - **阶段六**(测试):1 天 **总计**:约 7-10 个工作日 --- ## ✅ 检查清单 在每个阶段完成后,使用此清单验证: - [ ] 所有文件命名空间已更新 - [ ] 所有 using 语句已更新 - [ ] 项目文件已更新 - [ ] 解决方案文件已更新 - [ ] 代码编译无错误 - [ ] 应用程序可以正常启动 - [ ] 主要功能正常工作 - [ ] 已更新 modify.md 记录修改 --- ## 📝 修改记录 每次完成一个重要步骤后,请在 `modify.md` 文件中记录: - 修改日期 - 修改内容 - 修改的文件列表 - 遇到的问题及解决方案 --- **文档创建日期**: 2025年1月 **最后更新**: 2025年1月 **状态**: 计划阶段