# AGENTS – C# WPF 上位机项目初始化规范 本文件为在本仓库中创建和维护 **新的 C# WPF 上位机项目** 的智能体提供统一操作规范,作用域覆盖整个仓库。 若某个子目录存在更深层级的 `AGENTS.md`,则以更具体的规则为准。 ## 适用说明 - 本仓库中的历史项目、样例项目、参考项目仅用于借鉴工程结构与协作方式,不视为新项目的默认业务实现。 - 新项目初始化时,优先采用 **.NET 8 + WPF + MVVM Toolkit + Generic Host/DI + NLog** 这一默认技术基线。 - 不要直接复制参考项目中的业务命名、设备协议、数据库模型、接口定义、配置项或目录命名,除非用户明确要求。 - 若用户仅要求“初始化项目”或“生成上位机骨架”,默认理解为生成一个结构清晰、可扩展、适合工业桌面应用的 WPF 工程,而不是复制旧项目的业务代码。 ## 推荐技术基线 - 平台:Windows - SDK:.NET 8 SDK - UI:WPF - 项目文件:SDK-style `.csproj` - 目标框架:`net8.0-windows` - 语言特性:`enable`、`enable` - MVVM:`CommunityToolkit.Mvvm` - 宿主与依赖注入:`Microsoft.Extensions.Hosting` - 日志:`NLog` + `NLog.Extensions.Logging` - 配置:`appConfig.json` + `appConfig.{Environment}.json` - 开发期敏感配置:`UserSecrets` 或环境变量 - 测试:优先单独测试项目,推荐 xUnit;UI 难测逻辑应下沉到 ViewModel 或 Service ## 新项目初始化骨架 若无额外约束,推荐使用如下仓库结构: ```text src/ / .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/ .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/` 目录,直接在仓库根下放置 `/`;但若无明确要求,优先采用 `src/ + tests/` 结构。 ## 项目初始化最低要求 新建项目时,至少保证以下内容一次到位: - WPF 应用可以成功还原、编译、启动。 - `App.xaml.cs` 中建立统一的 Host/DI 启动入口。 - 主窗口与主要 ViewModel 通过依赖注入创建。 - 日志系统已接入,且启动阶段异常可落日志。 - 配置文件支持环境分层加载。 - 输出目录包含 `appConfig.json`、`appConfig.Development.json`、`NLog.config`。 - 为未来扩展预留 `Services`、`ViewModels`、`Views`、`Utils`、`Modules` 目录。 - 若涉及设备通信、轮询、文件监控、批处理等后台任务,必须预先考虑取消、限流、异常记录与 UI 线程切换。 ## 构建 / 还原 / 运行 / 发布 以下命令中的 `` 代表新建 WPF 项目名: - 创建解决方案:`dotnet new sln -n ` - 创建 WPF 项目:`dotnet new wpf -n --framework net8.0` - 还原:`dotnet restore src//.csproj` - 调试构建:`dotnet build src//.csproj -c Debug` - 发布构建:`dotnet build src//.csproj -c Release` - 运行(UI):`dotnet run --project src//.csproj -c Debug` - 发布示例:`dotnet publish src//.csproj -c Release -r win-x64 --self-contained false` 初始化或修改 `.csproj` 时,至少保持以下属性: - `true` - `net8.0-windows` - `enable` - `enable` 若项目包含配置、日志、资源或字典文件,需要同步设置 `CopyToOutputDirectory`,确保运行目录完整。 ## 测试 / 验证 - 新项目默认应预留独立测试项目:`tests/.Tests/`。 - 优先测试 ViewModel、Service、配置装配、解析逻辑、队列/调度逻辑,不要把核心逻辑压在难以测试的 code-behind 中。 - 若功能与 UI 强绑定,应先抽离为接口或服务,再进行单元测试或集成测试。 - 若暂未建立测试项目,至少执行一次构建验证,并手动完成关键 UI 流程检查。 - 单元测试示例:`dotnet test --filter FullyQualifiedName~命名空间.类名.方法名` - 提交前最低要求:`dotnet build` 成功;涉及关键逻辑时应补充对应测试。 ## Lint / 格式 - 若仓库尚未提供统一格式化工具或 `.editorconfig`,保持现有风格一致,不擅自引入新的格式化方案。 - 保持 using 简洁,移除未使用引用。 - 使用文件作用域命名空间,除非现有项目明确不采用。 - 避免只为“看起来更优雅”而大范围重排代码格式。 ## XML 文档注释规则 - 所有 `public` / `internal` / `protected` 类、接口、记录、方法、属性必须有 **中文 XML 文档注释**。 - 私有成员若逻辑不简单,或方法体超过 10 行,也应补充 XML 注释。 - 方法注释必须包含: - `` - 每个参数的 `` - 有返回值时的 `` - 可能抛出异常时的 `` - 异步方法名必须以 `Async` 结尾。 - 若方法接收 `CancellationToken`,需要在注释中写明取消行为及影响。 - 涉及命令、绑定、Dispatcher、后台线程、Task.Run、定时器、轮询、文件监控时,注释必须明确线程模型和触发行为。 - 已有 XML 注释不得删除;修改实现后必须同步更新注释内容。 ## 代码风格(通用 C#) - 命名空间使用文件作用域写法。 - 可读性优先:类型不明显时使用显式类型,明显时可使用 `var`。 - 字段优先使用 `private readonly`,字段命名采用 `_camelCase`。 - 常量使用 `const PascalCase`。 - 参数校验只放在系统边界:用户输入、外部接口、文件内容、网络返回、硬件返回等位置。 - 不要为当前需求之外的场景做预留抽象。 - 不要新增只被调用一次的帮助类、工具类或接口。 - 不要为了兼容历史命名而保留无意义的中间层,确认无用即可删除。 ## MVVM / WPF 实践 - 业务逻辑放在 ViewModel 或 Service,code-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` 进行日志记录,优先使用结构化日志。 - 记录错误时使用包含异常对象的重载,例如:`_logger.LogError(ex, "消息 {上下文}", value)`。 - 不要静默吞异常;至少按 Debug / Warning / Error 级别记录。 - 对用户可感知的失败,要同时提供用户友好提示与详细日志。 - 对启动失败、配置错误、设备离线、文件访问失败、网络错误等场景,应明确记录上下文。 - 对于可恢复错误,应在日志中记录恢复动作;对于不可恢复错误,应阻止继续执行并给出清晰提示。 ## 配置与环境管理 - 配置文件默认采用: - `appConfig.json` - `appConfig.Development.json` - 如有必要再增加 `appConfig.Production.json`、`appConfig.Local.json` 等 - 运行环境通过 `DOTNET_ENVIRONMENT` 或 `ASPNETCORE_ENVIRONMENT` 识别,默认 `Production`。 - 不要硬编码密钥、口令、连接串、IP、账号。 - 开发期敏感配置优先使用 `UserSecrets` 或环境变量。 - 新增配置文件、资源文件、字典文件时,必须同步 `.csproj` 的输出复制规则。 - 读取配置时优先建立强类型 Options 或清晰的数据模型,不散落魔法字符串。 ## 集合、并发与 I/O - 文件处理优先使用流式 API,如 `Directory.EnumerateFiles`,避免一次性加载大量文件。 - 批处理、轮询、文件监控、设备通信等后台任务需具备可取消性。 - 对共享状态使用明确的并发策略:`SemaphoreSlim`、`ConcurrentQueue`、`ConcurrentDictionary`、Channel 或串行队列。 - 不要锁住 UI 线程等待后台结果。 - 对缓冲区、日志列表、待处理队列要设置上限,避免内存无限增长。 - 所有后台任务都必须定义“谁创建、谁取消、谁记录异常、谁负责收尾”。 ## 命名约定 - 类 / 结构 / 记录 / 枚举:`PascalCase` - 接口:`I` 前缀 + `PascalCase` - 方法 / 属性 / 事件:`PascalCase` - 私有字段:`_camelCase` - 局部变量 / 参数:`camelCase` - 命令:`*Command` - 异步方法:`*Async` - 配置类型名应与配置节含义一致,不使用模糊命名如 `ConfigHelper`、`DataManager`、`CommonUtil` ## 新项目初始化完成的判定标准 一个新建 WPF 上位机项目,至少达到以下状态才可认为“初始化完成”: - 可以成功 `restore`、`build`、`run` - 主窗口可以正常显示 - Host / DI 已接入,主窗口和主 ViewModel 不依赖手工拼装 - 配置文件可被读取,环境分层生效 - 日志文件或日志输出可验证 - 核心目录结构已建立 - 至少保留一个可扩展的 Service、一个可扩展的 ViewModel、一个基础页面或主窗口示例 - 若已经接入设备/文件监听/后台任务,则具备最基本的取消与异常记录机制 ## 贡献检查清单 - 是否遵循本文件规定的初始化骨架与技术基线。 - 是否保持业务逻辑不进入 code-behind。 - 是否为公开成员补齐中文 XML 注释。 - 是否已接入 Host/DI、配置和日志。 - 是否移除未使用 using、无意义抽象和一次性工具层。 - 是否避免硬编码敏感信息。 - 是否在涉及后台任务时明确线程切换、取消与异常处理。 - 是否为新增配置/资源设置输出复制规则。 - 是否在提交前至少执行一次 `dotnet build`。 ## 快速命令速查 - 新建解决方案:`dotnet new sln -n ` - 新建 WPF 项目:`dotnet new wpf -n --framework net8.0` - 添加到解决方案:`dotnet sln add src//.csproj` - 还原:`dotnet restore src//.csproj` - 调试构建:`dotnet build src//.csproj -c Debug` - 发布构建:`dotnet build src//.csproj -c Release` - 运行调试:`dotnet run --project src//.csproj -c Debug` - 发布示例:`dotnet publish src//.csproj -c Release -r win-x64 --self-contained false` - 单测示例:`dotnet test --filter FullyQualifiedName~命名空间.类名.方法名` ## 额外说明 - 如果后续在某个新项目目录下生成了更具体的 `AGENTS.md`,应把该项目特有的设备协议、数据库约束、部署方式、配置项和 UI 行为写入子级文档,而不是污染仓库级规则。 - 仓库级 `AGENTS.md` 应保持“可复用、可初始化、不过度绑定具体业务”的定位。