WPF 插件化架构实践(工业级上位机专篇)
WPF 插件化(Plugin Architecture)是指将应用程序设计成主程序 + 多个独立插件(Plugin/Module)的形式,主程序提供基础框架(Shell、Region、DI容器、导航等),插件可以动态加载、卸载或按需启用,实现高可扩展性、热插拔、现场定制。
在工业上位机领域,插件化架构特别重要:
- 不同产线/客户需求差异大(报警规则、趋势曲线、配方管理、MES接口、视觉检测等)。
- 现场升级时,只需替换或新增插件DLL,无需重新编译整个系统。
- 支持多人并行开发、独立测试和部署。
- 长时间运行的系统更容易控制资源和稳定性。
主流实现方式对比(2026年推荐):
| 方式 | 优点 | 缺点 | 工业推荐场景 |
|---|---|---|---|
| Prism + DirectoryModuleCatalog | 官方支持、与MVVM/Region/DI深度集成、简单可靠 | 隔离性一般(同一AppDomain) | 首选,大多数工业上位机 |
| Prism + MEF | 自动发现、Export/Import更灵活 | 配置稍复杂 | 需要更强自动发现时 |
| 纯MEF | 轻量、插件发现强大 | 缺少Prism的导航/Region支持 | 小型插件系统 |
| MAF / AppDomain隔离 | 强隔离、容错性高 | 复杂、性能开销大 | 极高安全需求(极少用) |
工业级推荐方案:Prism + 动态模块加载(DirectoryModuleCatalog),结合 DI、Region、EventAggregator,形成完整插件化架构。本文以Prism为主,兼顾MEF混合使用。
1. 整体架构设计(推荐结构)
WPFPluginHMI.sln
├── Shell (主程序)
│ ├── App.xaml.cs ← 配置DI + DirectoryModuleCatalog
│ ├── Shell.xaml ← 定义多个Region
│ └── ShellViewModel.cs
├── Core ← 共享接口、Model、Constants、Converters
├── Infrastructure ← 全局服务(PLC、Log、Config)
├── Modules ← 插件文件夹(运行时)
│ ├── AlarmPlugin ← 报警插件
│ ├── TrendPlugin ← 趋势插件
│ ├── RecipePlugin ← 配方插件
│ └── VisionPlugin ← 视觉插件(示例)
└── Plugins (可选) ← 额外插件目录
- Core:所有插件只依赖接口(IAlarmService、IPlcService等),实现真正解耦。
- Modules:每个插件是一个独立类库,编译后DLL放入运行目录的
Modules文件夹。
2. 核心实现步骤
步骤1:主程序配置动态插件加载
在 App.xaml.cs 中:
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
var directoryCatalog = new DirectoryModuleCatalog
{
ModulePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules")
};
// 支持多个目录
// directoryCatalog.ModulePaths.Add("Plugins");
moduleCatalog.Add(directoryCatalog);
// 可混合固定模块(开发调试用)
// moduleCatalog.AddModule<CoreModule>();
}
步骤2:创建插件(以AlarmPlugin为例)
// AlarmPlugin/AlarmModule.cs
[Module(ModuleName = "AlarmPlugin", OnDemand = false)]
[ModuleDependency("TrendPlugin")] // 可选依赖
public class AlarmModule : IModule
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IAlarmService, AlarmService>();
containerRegistry.RegisterForNavigation<AlarmListView, AlarmListViewModel>();
containerRegistry.RegisterDialog<AlarmConfirmDialog, AlarmConfirmDialogViewModel>();
}
public void OnInitialized(IContainerProvider containerProvider)
{
var regionManager = containerProvider.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion("AlarmRegion", typeof(AlarmListView));
var alarmService = containerProvider.Resolve<IAlarmService>();
alarmService.StartMonitoring(); // 启动插件业务
}
}
步骤3:Shell中定义区域,插件自动填充
<!-- Shell.xaml -->
<Grid>
<ContentControl prism:RegionManager.RegionName="NavigationRegion" Width="220"/>
<ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="220,0,0,0"/>
<ContentControl prism:RegionManager.RegionName="AlarmRegion" /> <!-- 插件可注入此处 -->
</Grid>
步骤4:跨插件通信(EventAggregator)
在Core中定义事件:
public class AlarmOccurredEvent : PubSubEvent<AlarmItem> { }
插件中发布/订阅,实现松耦合联动。
3. 工业级增强实践
-
Post-build自动复制DLL
每个插件项目添加:xcopy "$(TargetDir)*.dll" "$(SolutionDir)Modules\" /Y /I /D -
按需加载(OnDemand)
重型插件(如视觉处理、报表生成)使用InitializationMode.OnDemand,在用户点击菜单时通过IModuleManager.LoadModule("VisionPlugin")加载。 -
MEF混合增强发现能力(可选)
如果需要更强的自动导出/导入,可在Prism中集成MEF容器(Prism.Mef),使用[Export]/[Import]特性自动发现插件服务。 -
插件安全与容错
- 订阅
IModuleManager事件记录加载日志。 - 单个插件异常不影响主程序(try-catch + 日志)。
- 生产环境增加DLL签名校验。
- 订阅
-
热更新策略
- 推荐:短暂停机 → 替换DLL → 重启(工业可接受)。
- 高级:结合AppDomain隔离(复杂,不推荐常规使用)。
-
权限与配置
- 插件可通过配置文件(或DI注入的IConfigService)决定是否启用。
- 按钮/菜单动态显示基于插件加载状态。
4. 完整工业上位机插件化示例功能
- AlarmPlugin:实时报警扫描 + 确认弹窗 + 联动Event。
- TrendPlugin:LiveCharts2趋势曲线,支持多PLC标签。
- RecipePlugin:配方编辑、下发PLC、版本管理。
- VisionPlugin:Halcon/OpenCvSharp集成,图像处理插件(OnDemand加载)。
5. 最佳实践总结
- 接口驱动:Core中定义所有接口,插件只实现接口。
- Region + 导航:主画面动态切换插件视图。
- EventAggregator:插件间零耦合通信。
- DI容器统一管理:所有服务通过Prism容器注入。
- 动态目录:生产环境必用
DirectoryModuleCatalog。 - 日志与监控:所有插件加载/异常必须记录。
- 测试策略:每个插件独立单元测试,注入Mock服务。
这种架构让你的WPF上位机像“搭积木”一样灵活:基础Shell + 通用Core + N个插件,根据不同工厂需求快速组合或现场新增功能。
立即实践建议:
- 基于之前我们学习的Prism项目,创建
Modules文件夹和2-3个插件项目。 - 配置
DirectoryModuleCatalog,实现自动加载。 - 在Shell中定义多个Region,让插件视图自动注入。
- 添加一个跨插件的EventAggregator事件(例如报警触发趋势刷新)。
- 测试:新增/移除一个插件DLL,观察是否热生效(重启后)。
完成这个实践后,你的WPF上位机就具备了真正的工业级插件化能力。
下一步推荐(请告诉我你的选择):
- Prism EventAggregator 详解(跨插件通信,必学)
- 工业级自定义Shell与Dialog样式(无边框深色工厂风格)
- PLC实时通信 + 插件化数据绑定实战
- 完整小型插件化上位机项目代码框架
你当前项目中遇到什么具体问题(动态加载失败、插件间通信、资源释放等)?随时贴代码,我帮你优化。
我们继续把这个插件化架构落地成可直接用于产线的工业上位机!随时告诉我你的进度。🚀
&spm=1001.2101.3001.5002&articleId=160309043&d=1&t=3&u=5973c9cd3b944dac838636142a450999)
3065

被折叠的 条评论
为什么被折叠?



