You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

12 KiB

AuroraDesk 项目重构计划

📋 项目概述

目标项目名: AuroraDesk
原项目名: MyAvaloniaApp
目标架构: 整洁架构 (Clean Architecture)
重点优化: 减少 ViewModels 耦合,提高代码可维护性
环境: Windows 10
注意事项: 避免使用 Linux 语法,防止乱码问题


🎯 重构目标

1. 项目重命名

  • 项目名称:MyAvaloniaAppAuroraDesk
  • 解决方案文件:MyAvaloniaApp.slnAuroraDesk.sln
  • 项目文件:MyAvaloniaApp.csprojAuroraDesk.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 命名空间规划

// 核心领域层
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, TabItemCore.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 的代码
  • 注入 INavigationServiceIPageViewModelFactory
  • 简化 MainWindowViewModel 的职责
  • 更新所有命名空间为 AuroraDesk.Presentation.*

阶段三:项目重命名(谨慎执行)

步骤 3.1: 重命名项目文件

  • 重命名 .csproj 文件
  • 重命名 .sln 文件
  • 更新项目文件中的 <RootNamespace><AssemblyName>

步骤 3.2: 重命名命名空间(逐个文件修改)

  • 不要使用批量替换
  • 逐个文件修改命名空间声明
  • 逐个文件更新 using 语句
  • 每次修改后编译测试

步骤 3.3: 更新配置文件

  • 更新 appsettings.json 中的项目相关配置
  • 更新 app.manifest 中的程序集名称
  • 更新所有批处理文件和脚本

阶段四:解耦 ViewModels(重点)

步骤 4.1: 创建工厂接口和实现

// AuroraDesk.Application/Services/IPageViewModelFactory.cs
public interface IPageViewModelFactory
{
    T CreatePageViewModel<T>(IScreen screen) where T : IRoutableViewModel;
    IRoutableViewModel CreatePageViewModel(string pageId, IScreen screen);
}

步骤 4.2: 实现工厂类

// 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<DashboardPageViewModel>(),
            "users" => _serviceProvider.GetRequiredService<UsersPageViewModel>(),
            // ... 其他页面
            _ => throw new ArgumentException($"Unknown page: {pageId}")
        };
    }
}

步骤 4.3: 创建导航服务

// AuroraDesk.Application/Services/INavigationService.cs
public interface INavigationService
{
    ObservableCollection<NavigationItem> GetNavigationItems();
    void NavigateToPage(NavigationItem item);
}

步骤 4.4: 重构 MainWindowViewModel

  • 移除 InitializeNavigationItems 方法中的 ViewModel 创建逻辑
  • 注入 INavigationService 获取导航项
  • 使用 IPageViewModelFactory 创建 ViewModel
  • 简化导航逻辑,委托给 INavigationService

阶段五:注册依赖注入

步骤 5.1: 更新 ServiceCollectionExtensions

  • 注册 IPageViewModelFactoryPageViewModelFactory
  • 注册 INavigationServiceNavigationService
  • 注册所有 PageViewModel 为 Transient(或 Scoped)
  • 更新命名空间引用

步骤 5.2: 更新 App.axaml.cs

  • 确保所有新服务正确注册
  • 更新 ViewLocator 的命名空间
  • 测试依赖注入是否正常工作

阶段六:测试和验证

步骤 6.1: 编译测试

  • 清理解决方案并重新编译
  • 修复所有编译错误
  • 修复所有命名空间引用错误

步骤 6.2: 运行时测试

  • 启动应用程序
  • 测试导航功能
  • 测试所有页面能否正常加载
  • 测试标签页功能

步骤 6.3: 代码检查

  • 检查是否还有直接 new ViewModel 的地方
  • 检查命名空间是否全部更新
  • 检查是否有循环依赖

🔧 技术实现细节

1. PageViewModel 注册方式

// ServiceCollectionExtensions.cs
services.AddTransient<DashboardPageViewModel>();
services.AddTransient<UsersPageViewModel>();
services.AddTransient<SettingsPageViewModel>();
// ... 其他 PageViewModel

2. 导航配置数据

// NavigationConfig.cs
public class NavigationConfig
{
    public List<NavigationItemConfig> 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<NavigationItemConfig>? Children { get; set; }
}

3. MainWindowViewModel 重构示例

重构前:

private void InitializeNavigationItems()
{
    _navigationItems = new ObservableCollection<NavigationItem>
    {
        new NavigationItem { ViewModel = new DashboardPageViewModel(_screen) },
        new NavigationItem { ViewModel = new UsersPageViewModel(_screen) },
        // ...
    };
}

重构后:

private readonly INavigationService _navigationService;

public MainWindowViewModel(
    IScreen screen, 
    INavigationService navigationService,
    ILogger<MainWindowViewModel>? 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月
状态: 计划阶段