跳转到主内容

SeatFlow 架构分层、技术栈、关键设计决策和策略管道概念

架构总览

项目目标

SeatFlow 是一个 .NET 10 跨平台桌面座位编排系统,面向学校、培训机构和企业等需要批量座位安排的场景。系统核心能力包括:

  • 多策略排座管道(固定座位、前排轮换、同桌分组、性别限制、历史防重复等)
  • 多种教室布局支持(网格、极坐标、自由点)
  • 多数据源导入(CSV、XLSX、JSON)
  • 排座结果导出(Excel、CSV、PDF、图片)
  • 历史快照与回滚
  • 插件化扩展(Assembly 插件 + Lua/C# 脚本)
  • 完整的国际化支持(zh-CN/en-US等)

分层架构

采用经典三层架构 + 插件化扩展,遵循严格的分层依赖原则:

                    ┌─────────────────────────────────────┐
                    │         Presentation.Avalonia        │
                    │   Avalonia UI 12 + CommunityToolkit  │
                    │         MVVM, 编译绑定, i18n         │
                    └─────────────────────────────────────┘
                                      │
                    ┌─────────────────────────────────────┐
                    │            Application              │
                    │    IApplicationFacade (外观)         │
                    │    StrategyExecutionPipeline        │
                    │    PluginManager + CommandHistory   │
                    │    DI 容器 (Microsoft.Extensions)    │
                    └─────────────────────────────────────┘
                                      │
            ┌─────────────────────────┼─────────────────────────┐
            │                         │                         │
   ┌────────▼──────┐       ┌─────────▼────────┐    ┌───────────▼────┐
   │     Core      │       │    Contracts      │    │ Infrastructure │
   │               │       │                   │    │                │
   │ ┌───────────┐ │       │ IPluginSeating    │    │ Csv/Xlsx/Json  │
   │ │  Entities │ │       │ Strategy          │    │ Providers      │
   │ │  Student  │ │       │ (插件跨层契约)     │    │ Exporters      │
   │ │  Seat     │ │       │                   │    │ Repositories   │
   │ │  Layout   │ │       └───────────────────┘    │ LayoutBuilders │
   │ ├───────────┤ │                                 │ MigrationSys  │
   │ │ Strategies│ │                                 └────────────────┘
   │ │ Interfaces│ │
   │ │ 7 Builtin │ │
   │ │ Strategies│ │
   │ ├───────────┤ │
   │ │ Domain    │ │
   │ │ Services  │ │
   │ └───────────┘ │
   └───────────────┘

各层职责

项目 核心职责
Core SeatFlow.Core 领域实体、策略接口和实现、领域服务、工作区、数据提供者接口
Contracts SeatFlow.Contracts 跨层契约,供外部插件引用的插件策略接口
Infrastructure SeatFlow.Infrastructure 数据提供者实现、导出器、布局构建器、仓库、文件迁移系统、序列化
Application SeatFlow.Application UI 单一入口(外观)、策略管道执行器、命令模式、插件管理、DI 注册、脚本适配器
Plugins.Sdk SeatFlow.Plugins.Sdk 轻量级 SDK 程序集,供外部插件作者引用
Presentation SeatFlow.Presentation.Avalonia Avalonia 12 桌面应用,MVVM 架构

依赖关系链

Presentation.Avalonia
  └── Application
        ├── Core
        ├── Contracts
        └── Infrastructure

Plugins.Sdk (仅被外部插件引用,不在主项目依赖链中)

技术栈

技术 版本 用途
.NET SDK 10 运行时和 SDK
Avalonia UI 12 跨平台桌面 UI 框架
CommunityToolkit.Mvvm 8.4 MVVM 源码生成器([ObservableProperty], [RelayCommand]
Serilog 4 结构化日志
EPPlus 8 XLSX 读写
QuestPDF PDF 导出
Microsoft.Extensions.DependencyInjection DI 容器
xUnit 3 单元测试框架
FluentAssertions 测试断言
NSubstitute 模拟框架

关键设计决策

项目采用架构决策记录(ADR)系统文档化重大技术决策,位于 docs/adr/ 目录。

ADR 索引

ADR 主题 关键结论
ADR-001 选择 Avalonia UI 跨平台(Windows/macOS/Linux),原生 MVVM,WPF 开发者友好
ADR-002 MVVM 框架 CommunityToolkit.Mvvm 源码生成器
ADR-003 分层架构 + 插件化 经典三层 + Contracts 层隔离插件接口
ADR-004 策略模式 ISeatingStrategy 作为排座算法通用接口
ADR-005 命令模式 IUndoableCommand + CommandHistory 实现撤销/重做
ADR-006 策略管道 Fill-in-Order 模型,依赖策略在 RandomFill 上下文中执行,能力声明系统
ADR-007 多策略插件包 双层清单(包级 plugins-manifest.json + 策略 manifest.json
ADR-008 引导系统示例数据注入 纯内存注入,零磁盘痕迹,DispatcherPriority.Background 延迟

核心架构模式

  • 外观模式: IApplicationFacade 是 UI 层的单一入口点,封装所有业务操作(40+ 方法)
  • 策略模式: ISeatingStrategyIDependentSeatingStrategy 定义排座算法接口
  • 命令模式: IUndoableCommand + CommandHistory 提供快照式撤销/重做
  • 插件隔离: 通过 AssemblyLoadContext 独立加载外部 DLL,支持热插拔
  • 依赖注入: Microsoft.Extensions.DependencyInjection 管理组件生命周期

策略管道概念

SeatFlow 的策略管道采用 Fill-in-Order 模型,核心原则:

  1. 按 Priority 降序执行:Priority 数值越大越先执行,先执行的策略优先挑选空座
  2. 不存在覆盖语义:先占的座位不会被后执行的策略推翻
  3. IsFixed 保护:固定座位标记 IsFixed=true,后续 GetEmptySeats() 自动排除
  4. 依赖策略:某些策略(DeskMate、GenderRestrictedSeat、NoRepeatDeskMate)不在外部管道执行,而是在 RandomFill 的分配循环中按上下文内部优先级评估

管道执行顺序

独立策略 Priority 降序 →
  FixedSeat(100)     ← 最先执行:锁定固定座位
  FrontRowRotation(50) ← 在非固定空座中填前排
  RandomFill(1)      ← 兜底填充:
    └─ 依赖策略(优先级降序)→
       DeskMate(50)              ← 检查同桌关系
       GenderRestrictedSeat(45)  ← 检查性别限制
       NoRepeatDeskMate(40)      ← 检查历史同桌重复
  Defrag(0)         ← 碎片整理(默认禁用)

能力声明系统

策略需在 manifest 中声明所需能力(如 MarkFixedSeat),运行时方可调用对应接口。这提供了一个可扩展的约束和日志机制。参见 SeatFlow.Core/Strategies/Capability.cs

插件系统概念

SeatFlow 支持三种方式扩展排座策略:

  1. Assembly 插件:编译为 DLL,实现 IPluginSeatingStrategy,通过 AssemblyLoadContext 隔离加载
  2. Lua 脚本插件:逻辑由 Lua 脚本文件描述,在受限沙箱中执行
  3. C# 脚本插件:逻辑由 C# Script 文件描述

插件采用双层清单架构 (docs/adr/ADR-007-multi-strategy-plugin-packages.md):

Plugins/{packageId}/
├── plugins-manifest.json   ← 包级清单(元数据 + 加载指令)
├── strategy_id/
│   ├── manifest.json       ← 策略级清单(StrategyManifest 格式)
│   └── strategy.dll
└── data/
    └── enables.json        ← 运行时启用状态