编辑 | blame | 历史 | 原始文档

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. 本次是静态代码与配置结构分析,未执行完整编译和设备联机验证;图中的外设关系来自代码调用与项目引用,不代表现场端口、协议参数或许可已验证。