# TapProject 代码结构分析 ## 1. 分析范围与结论 - 分析目录:`D:\TestPlatform\TapProject` - 源码规模:45 个内部 `.csproj`、476 个 C# 文件、157 个 XAML 文件(均排除 `bin/obj/MigrationBackup`)。 - 技术基线:全部面向 .NET Framework 4.7.2;其中 33 个旧式工程使用 `v4.7.2`,12 个 SDK 风格工程使用 `net472`。 - 总体形态:这是一个 WPF 桌面测试平台,采用“主宿主 + 公共 HMI 框架 + 权限驱动的动态插件 + 设备/测试执行适配器”的模块化单体架构。 - 核心业务:`Plugin.BurnIn` 负责老化炉/穴位 UI、扫码、PLC 状态、MES 校验、测试执行消息处理、曲线和结果持久化;执行引擎通过 `ITestExecutionWrapper` 在 NI TestStand 与 OpenTAP 之间切换。 对应图见 `TapProject_代码结构.drawio`: 1. `01-总体分层结构`:展示代码模块分层、关键依赖和外部系统。 2. `02-运行时与老化主链路`:展示启动、登录、权限菜单、动态装载、插件生命周期以及老化测试数据链路。 ## 2. 代码模块分层 | 层级 | 主要工程 | 职责 | |---|---|---| | WPF 宿主 | `WPFProject/TapProject.csproj` | 单实例启动、日志/语言/资源初始化、登录、装载进度、主窗口和页签承载 | | 插件契约与装载 | `HMI.Core`、`HMI.Base` | `IPlugin`/`IPluginContainer` 生命周期契约、`PluginLoader`、插件基类、反射兼容包装 | | 公共 UI 与工具 | `HMI.UI`、`HMI.StdControl`、`HMI.Util`、`HMI.Util.Base`、`HMI.Simple.Util`、`HMI.LogUtil`、`HMI.SerialData.Util`、`HMI.MQUtil` | WPF 控件/样式、绑定转换器、路径/配置/序列化、日志、串口、MSMQ 等通用能力 | | 系统管理 HMI | `HMI.MenuManage`、`HMI.SettingControl`、`HMI.ParameterManage`、`HMI.AlarmInfoManage`、`HMI.DataViewer`、`HMI.LogViewer` | 用户/角色/菜单、系统设置、参数、报警、数据和日志查询 | | 老化与设备业务插件 | `Plugin.BurnIn`、`Plugin.CurrentSensorControl`、`Plugin.DOControl`、`Plugin.DODriverControl`、`Plugin.ModelManage`、`Plugin.JarUI` | 老化测试主界面、电流/DO 控制、型号与工装界面 | | 测试执行与编辑 | `Plugin.TsExecution`、`Plugin.StandardTest`、`Plugin.TestPlanEditor`、`Plugin.SeqEditor`、`Plugin.TsSupport`、`HMI.TapApi`、`Util.ManualDebug` | TestStand/OpenTAP 抽象、序列执行、计划/步骤编辑、手动调试 | | 数据与报告插件 | `Plugin.TestResult`、`Plugin.DataViewer`、`Plugin.DataBoard`、`Plugin.QualityReport` | 测试结果、业务数据、看板、质量报表 | | 设备与通信适配 | `PLCHelper`、`S7Driver`、`OPCClient`、`ModBusTcpController`、`DIOController`、`ConnectionUtil`、`CellStepSender` | S7 PLC、OPC、Modbus TCP、DIO、TCP/步骤发送等底层接入 | | 辅助程序 | `HMI.UnitTest`、`ConsoleTest`、`StationGlobalsReader` | 集成测试壳、控制器控制台试验、TestStand StationGlobals 读取 | ## 3. 运行时主链路 1. `App.Application_Startup` 执行单实例保护,注册兼容组件,初始化日志、语言、系统设置和 Toast,然后显示登录窗口(`WPFProject/App.xaml.cs:94-119`)。 2. `Login` 从 SQLite 的 `user / role / user_role_rel / role_menu_rel / menu` 表读取用户与权限菜单,并写入全局 `UserInfo`(`WPFProject/Login.xaml.cs:59-130`)。 3. `LoadingWindow` 初始化报警服务并调用 `PluginLoader.LoadMenuAndPlugin`(`WPFProject/LoadingWindow.xaml.cs:107-118`)。 4. `PluginLoader` 根据当前用户的 `AllPermissions` 拼出菜单树,从 `Plugin` 目录加载 DLL,按数据库中的 `className` 反射创建实例,注入日志和插件私有配置目录,调用 `InitFinish` 并挂接关闭事件(`HMI.Base/PluginLoader.cs:52-123`)。 5. `PanuonWindow` 是 `IPluginContainer`;`MainTabControl` 在切换菜单时调用插件的 `CanDeActive / DeActive / CanActive / Active`,把 WPF 或 WinForms 内容装入宿主页(`WPFProject/Controls/MainTabControl.xaml.cs:138-181`)。 这意味着菜单、权限和插件类型并非只由编译引用决定;部署目录中的 DLL、SQLite 菜单数据及用户角色共同决定实际运行时界面。 ## 4. 老化业务主链路 - `Plugin.BurnIn.BurnInUI` 继承 `PluginMaskControl`,初始化 S7 PLC 上下文,读取产品/公共参数、扫码配置和主测试序列(`Plugin.BurnIn/BurnInUI.xaml.cs:25,105,179-222`)。 - 序列扩展名为 `.tapplan` 时选择 `TapWrapper`,否则选择 `TeststandWrapper`;两者都实现 `ITestExecutionWrapper`,向上统一提供序列启动、StationGlobals/FileGlobals 和 UI 消息(`Plugin.BurnIn/TestResultView.xaml.cs:209-263`、`Plugin.TsSupport/ITestExecutionWrapper.cs`)。 - 执行引擎以事件码 `10014` 和方法码驱动炉体/穴位状态、计数、曲线、提示和结果保存;结果可落地到 SQLite 与 CSV(`Plugin.BurnIn/TestResultView.xaml.cs:300-603`、`Plugin.BurnIn/SingleCell.xaml.cs:950-1030`)。 - `Scanner` 通过串口读码,业务参数决定 MES 站位;`PNUtil` 通过 HTTP 调用 MES 获取 PN 和过站校验(`Plugin.BurnIn/Scanner.xaml.cs`、`Plugin.BurnIn/Util/PNUtil.cs:27-84`)。 - `BurnInUI` 与 `SingleCell/Cooler` 通过 `PLCHelper.S7Context` 读写 `BurnInControler` PLC(`Plugin.BurnIn/Util/RunTimeVariablePool.cs`、`Plugin.BurnIn/SingleCell.xaml.cs:1107-1124`)。 ## 5. 重要边界与风险 1. **当前检出无法独立完整编译。** 静态解析发现 17 条未解析 `ProjectReference`,涉及 7 个工程;缺失源树包括 `D:\Project\OpenTapEditor`、`D:\TestPlatform\OpenTapEditor` 与 `D:\VisualStudio\UILib/UtilLib`。图中把它们标为“外部/当前缺失”,而不是本仓库已具备的模块。 2. **插件化并非完全解耦。** 主工程同时直接引用大量插件项目,又在运行时依据数据库反射加载插件 DLL;这是“编译期聚合 + 运行时菜单插件化”的混合模式。 3. **样例菜单库与源码存在漂移。** `WPFProject/Config/Database/database.db` 的 `menu` 表当前有 13 条记录(2 个一级目录、11 个叶子项),其中引用 `HMI.IOMonitor.dll`,但源码目录不存在;同时 `Plugin.BurnIn` 等已编译工程未出现在该样例菜单表中。部署版数据库可能不同,不能把样例库视为最终功能清单。 4. **运行目录是隐式依赖。** `PathHelper` 用 `Path.GetFullPath(".")` 作为根目录,`Plugin/Config/Icon/Lang` 等路径取决于进程工作目录,而不完全取决于 EXE 所在目录。 5. 本次是静态代码与配置结构分析,未执行完整编译和设备联机验证;图中的外设关系来自代码调用与项目引用,不代表现场端口、协议参数或许可已验证。