Files
Axi_Omron/AGENTS.md
yunxiao.zhu 49f113dcf3 feat: 初始化 PCB 检测 WPF 应用程序
* 创建 AxiOmron.PcbCheck 项目主框架及解决方案
* 添加 Dashboard 和系统设置页面
* 实现 Modbus TCP PLC、扫码枪、SFTP 查询等核心服务
* 集成 Andon 报警、工作流托管服务与日志配置
* 补充项目文档和 UI 设计规范
2026-04-17 10:43:51 +08:00

13 KiB
Raw Blame History

AGENTS C# WPF 上位机项目初始化规范

本文件为在本仓库中创建和维护 新的 C# WPF 上位机项目 的智能体提供统一操作规范,作用域覆盖整个仓库。 若某个子目录存在更深层级的 AGENTS.md,则以更具体的规则为准。

适用说明

  • 本仓库中的历史项目、样例项目、参考项目仅用于借鉴工程结构与协作方式,不视为新项目的默认业务实现。
  • 新项目初始化时,优先采用 .NET 8 + WPF + MVVM Toolkit + Generic Host/DI + NLog 这一默认技术基线。
  • 不要直接复制参考项目中的业务命名、设备协议、数据库模型、接口定义、配置项或目录命名,除非用户明确要求。
  • 若用户仅要求“初始化项目”或“生成上位机骨架”,默认理解为生成一个结构清晰、可扩展、适合工业桌面应用的 WPF 工程,而不是复制旧项目的业务代码。

推荐技术基线

  • 平台Windows
  • SDK.NET 8 SDK
  • UIWPF
  • 项目文件SDK-style .csproj
  • 目标框架:net8.0-windows
  • 语言特性:<Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings>
  • MVVMCommunityToolkit.Mvvm
  • 宿主与依赖注入:Microsoft.Extensions.Hosting
  • 日志:NLog + NLog.Extensions.Logging
  • 配置:appConfig.json + appConfig.{Environment}.json
  • 开发期敏感配置:UserSecrets 或环境变量
  • 测试:优先单独测试项目,推荐 xUnitUI 难测逻辑应下沉到 ViewModel 或 Service

新项目初始化骨架

若无额外约束,推荐使用如下仓库结构:

src/
  <ProjectName>/
    <ProjectName>.csproj
    App.xaml
    App.xaml.cs
    MainWindow.xaml
    MainWindow.xaml.cs
    appConfig.json
    appConfig.Development.json
    NLog.config
    Assets/
    Models/
    ViewModels/
    Views/
      Pages/
      UserControls/
    Services/
      Interfaces/
      Implementations/
    Modules/
    Utils/
tests/
  <ProjectName>.Tests/

约束如下:

  • App.xaml / App.xaml.cs 负责应用启动、Host 创建、全局异常处理、配置与日志装配。
  • MainWindow.xaml / .cs 只负责主窗口装配,不承载核心业务逻辑。
  • ViewModels/ 保存可绑定状态、命令和页面协调逻辑。
  • Views/Pages/Views/UserControls/ 保存页面和可复用视图组件。
  • Services/Interfaces/Services/Implementations/ 用于硬件通信、文件处理、MES/PLC/条码/图像处理等业务服务。
  • Modules/ 用于较独立的能力模块,例如数据库、设备协议封装、审计上传、报表导出等。
  • Utils/ 仅保留轻量、通用、无业务语义的辅助工具;不要把主要业务逻辑塞入工具类。
  • tests/ 必须与应用项目分离,避免把测试代码混入正式程序集。

若仓库当前只有单个应用项目,也可暂时不建 src/ 目录,直接在仓库根下放置 <ProjectName>/;但若无明确要求,优先采用 src/ + tests/ 结构。

项目初始化最低要求

新建项目时,至少保证以下内容一次到位:

  • WPF 应用可以成功还原、编译、启动。
  • App.xaml.cs 中建立统一的 Host/DI 启动入口。
  • 主窗口与主要 ViewModel 通过依赖注入创建。
  • 日志系统已接入,且启动阶段异常可落日志。
  • 配置文件支持环境分层加载。
  • 输出目录包含 appConfig.jsonappConfig.Development.jsonNLog.config
  • 为未来扩展预留 ServicesViewModelsViewsUtilsModules 目录。
  • 若涉及设备通信、轮询、文件监控、批处理等后台任务,必须预先考虑取消、限流、异常记录与 UI 线程切换。

构建 / 还原 / 运行 / 发布

以下命令中的 <ProjectName> 代表新建 WPF 项目名:

  • 创建解决方案:dotnet new sln -n <SolutionName>
  • 创建 WPF 项目:dotnet new wpf -n <ProjectName> --framework net8.0
  • 还原:dotnet restore src/<ProjectName>/<ProjectName>.csproj
  • 调试构建:dotnet build src/<ProjectName>/<ProjectName>.csproj -c Debug
  • 发布构建:dotnet build src/<ProjectName>/<ProjectName>.csproj -c Release
  • 运行UIdotnet run --project src/<ProjectName>/<ProjectName>.csproj -c Debug
  • 发布示例:dotnet publish src/<ProjectName>/<ProjectName>.csproj -c Release -r win-x64 --self-contained false

初始化或修改 .csproj 时,至少保持以下属性:

  • <UseWPF>true</UseWPF>
  • <TargetFramework>net8.0-windows</TargetFramework>
  • <Nullable>enable</Nullable>
  • <ImplicitUsings>enable</ImplicitUsings>

若项目包含配置、日志、资源或字典文件,需要同步设置 CopyToOutputDirectory,确保运行目录完整。

测试 / 验证

  • 新项目默认应预留独立测试项目:tests/<ProjectName>.Tests/
  • 优先测试 ViewModel、Service、配置装配、解析逻辑、队列/调度逻辑,不要把核心逻辑压在难以测试的 code-behind 中。
  • 若功能与 UI 强绑定,应先抽离为接口或服务,再进行单元测试或集成测试。
  • 若暂未建立测试项目,至少执行一次构建验证,并手动完成关键 UI 流程检查。
  • 单元测试示例:dotnet test --filter FullyQualifiedName~命名空间.类名.方法名
  • 提交前最低要求:dotnet build 成功;涉及关键逻辑时应补充对应测试。

Lint / 格式

  • 若仓库尚未提供统一格式化工具或 .editorconfig,保持现有风格一致,不擅自引入新的格式化方案。
  • 保持 using 简洁,移除未使用引用。
  • 使用文件作用域命名空间,除非现有项目明确不采用。
  • 避免只为“看起来更优雅”而大范围重排代码格式。

XML 文档注释规则

  • 所有 public / internal / protected 类、接口、记录、方法、属性必须有 中文 XML 文档注释
  • 私有成员若逻辑不简单,或方法体超过 10 行,也应补充 XML 注释。
  • 方法注释必须包含:
    • <summary>
    • 每个参数的 <param>
    • 有返回值时的 <returns>
    • 可能抛出异常时的 <exception>
  • 异步方法名必须以 Async 结尾。
  • 若方法接收 CancellationToken,需要在注释中写明取消行为及影响。
  • 涉及命令、绑定、Dispatcher、后台线程、Task.Run、定时器、轮询、文件监控时注释必须明确线程模型和触发行为。
  • 已有 XML 注释不得删除;修改实现后必须同步更新注释内容。

代码风格(通用 C#

  • 命名空间使用文件作用域写法。
  • 可读性优先:类型不明显时使用显式类型,明显时可使用 var
  • 字段优先使用 private readonly,字段命名采用 _camelCase
  • 常量使用 const PascalCase
  • 参数校验只放在系统边界:用户输入、外部接口、文件内容、网络返回、硬件返回等位置。
  • 不要为当前需求之外的场景做预留抽象。
  • 不要新增只被调用一次的帮助类、工具类或接口。
  • 不要为了兼容历史命名而保留无意义的中间层,确认无用即可删除。

MVVM / WPF 实践

  • 业务逻辑放在 ViewModel 或 Servicecode-behind 仅做视图装配、事件桥接、生命周期对接。
  • 命令优先使用 RelayCommand / AsyncRelayCommand
  • 可绑定属性优先使用 [ObservableProperty] 生成,不手写重复样板代码。
  • 长耗时操作必须使用 async/await,不得阻塞 UI 线程。
  • 后台线程不得直接更新绑定到 UI 的对象;涉及 UI 更新时必须切回 Dispatcher。
  • 不要在 View 中直接 new 业务服务。
  • 不要在 code-behind 中直接访问数据库、文件系统、MES、PLC、串口、相机或网络接口。
  • 页面切换、对话框协调、状态共享应优先通过 ViewModel 或应用级服务完成。
  • 若项目包含托盘、单实例、后台常驻、自动重连、设备轮询等能力,应将其建模为显式服务并通过 DI 管理生命周期。

宿主 / DI / 启动约定

  • App.xaml.cs 中集中创建 HostApplicationBuilder 或等价 Host 对象。
  • 所有服务、ViewModel、Window、Page 的注册集中管理,不要分散在多个随机文件中。
  • 优先使用构造函数注入,不使用服务定位器模式。
  • 应用启动顺序应清晰:配置加载 → 日志初始化 → Host 构建 → 服务注册 → 主窗口创建与显示。
  • 若涉及全局异常捕获、未观察任务异常、UI 线程异常,应在启动阶段完成统一挂接。
  • 若项目需要单实例约束,应采用明确、可维护的单实例方案,并保证启动顺序可追踪。

日志 / 异常 / 用户提示

  • 注入 ILogger<T> 进行日志记录,优先使用结构化日志。
  • 记录错误时使用包含异常对象的重载,例如:_logger.LogError(ex, "消息 {上下文}", value)
  • 不要静默吞异常;至少按 Debug / Warning / Error 级别记录。
  • 对用户可感知的失败,要同时提供用户友好提示与详细日志。
  • 对启动失败、配置错误、设备离线、文件访问失败、网络错误等场景,应明确记录上下文。
  • 对于可恢复错误,应在日志中记录恢复动作;对于不可恢复错误,应阻止继续执行并给出清晰提示。

配置与环境管理

  • 配置文件默认采用:
    • appConfig.json
    • appConfig.Development.json
    • 如有必要再增加 appConfig.Production.jsonappConfig.Local.json
  • 运行环境通过 DOTNET_ENVIRONMENTASPNETCORE_ENVIRONMENT 识别,默认 Production
  • 不要硬编码密钥、口令、连接串、IP、账号。
  • 开发期敏感配置优先使用 UserSecrets 或环境变量。
  • 新增配置文件、资源文件、字典文件时,必须同步 .csproj 的输出复制规则。
  • 读取配置时优先建立强类型 Options 或清晰的数据模型,不散落魔法字符串。

集合、并发与 I/O

  • 文件处理优先使用流式 APIDirectory.EnumerateFiles,避免一次性加载大量文件。
  • 批处理、轮询、文件监控、设备通信等后台任务需具备可取消性。
  • 对共享状态使用明确的并发策略:SemaphoreSlimConcurrentQueueConcurrentDictionary、Channel 或串行队列。
  • 不要锁住 UI 线程等待后台结果。
  • 对缓冲区、日志列表、待处理队列要设置上限,避免内存无限增长。
  • 所有后台任务都必须定义“谁创建、谁取消、谁记录异常、谁负责收尾”。

命名约定

  • 类 / 结构 / 记录 / 枚举:PascalCase
  • 接口:I 前缀 + PascalCase
  • 方法 / 属性 / 事件:PascalCase
  • 私有字段:_camelCase
  • 局部变量 / 参数:camelCase
  • 命令:*Command
  • 异步方法:*Async
  • 配置类型名应与配置节含义一致,不使用模糊命名如 ConfigHelperDataManagerCommonUtil

新项目初始化完成的判定标准

一个新建 WPF 上位机项目,至少达到以下状态才可认为“初始化完成”:

  • 可以成功 restorebuildrun
  • 主窗口可以正常显示
  • Host / DI 已接入,主窗口和主 ViewModel 不依赖手工拼装
  • 配置文件可被读取,环境分层生效
  • 日志文件或日志输出可验证
  • 核心目录结构已建立
  • 至少保留一个可扩展的 Service、一个可扩展的 ViewModel、一个基础页面或主窗口示例
  • 若已经接入设备/文件监听/后台任务,则具备最基本的取消与异常记录机制

贡献检查清单

  • 是否遵循本文件规定的初始化骨架与技术基线。
  • 是否保持业务逻辑不进入 code-behind。
  • 是否为公开成员补齐中文 XML 注释。
  • 是否已接入 Host/DI、配置和日志。
  • 是否移除未使用 using、无意义抽象和一次性工具层。
  • 是否避免硬编码敏感信息。
  • 是否在涉及后台任务时明确线程切换、取消与异常处理。
  • 是否为新增配置/资源设置输出复制规则。
  • 是否在提交前至少执行一次 dotnet build

快速命令速查

  • 新建解决方案:dotnet new sln -n <SolutionName>
  • 新建 WPF 项目:dotnet new wpf -n <ProjectName> --framework net8.0
  • 添加到解决方案:dotnet sln add src/<ProjectName>/<ProjectName>.csproj
  • 还原:dotnet restore src/<ProjectName>/<ProjectName>.csproj
  • 调试构建:dotnet build src/<ProjectName>/<ProjectName>.csproj -c Debug
  • 发布构建:dotnet build src/<ProjectName>/<ProjectName>.csproj -c Release
  • 运行调试:dotnet run --project src/<ProjectName>/<ProjectName>.csproj -c Debug
  • 发布示例:dotnet publish src/<ProjectName>/<ProjectName>.csproj -c Release -r win-x64 --self-contained false
  • 单测示例:dotnet test --filter FullyQualifiedName~命名空间.类名.方法名

额外说明

  • 如果后续在某个新项目目录下生成了更具体的 AGENTS.md,应把该项目特有的设备协议、数据库约束、部署方式、配置项和 UI 行为写入子级文档,而不是污染仓库级规则。
  • 仓库级 AGENTS.md 应保持“可复用、可初始化、不过度绑定具体业务”的定位。