一、架构概述
插件式架构是一种将系统功能模块化、支持动态扩展的软件设计模式。在 .NET Core 3.0 及之后的版本中,AssemblyLoadContext(简称 ALC)提供了程序集加载隔离能力,支持插件的独立加载、依赖隔离与热卸载,是实现现代化插件系统的核心基础设施。
1.1 核心优势
隔离加载:每个插件运行在独立的 ALC 中,避免版本冲突
可卸载性:支持插件热卸载,释放内存与资源
依赖隔离:插件可自带专属版本依赖,不与主程序冲突
动态扩展:运行时发现、加载、启用/禁用插件,无需重启主程序
1.2 典型应用场景
上位机软件的功能模块动态加载
业务系统的第三方扩展机制
规则引擎、脚本引擎的隔离执行
模块化 SaaS 平台的租户功能定制
二、AssemblyLoadContext 核心原理
2.1 基本概念
AssemblyLoadContext 是 .NET 运行时中负责程序集加载的抽象上下文。默认情况下,整个应用程序共享一个默认上下文(Default)。通过创建自定义 ALC,可以将插件程序集加载到独立上下文中,实现隔离。
2.2 关键特性
加载解析:每个 ALC 有独立的程序集解析逻辑
依赖共享:可设置将主程序程序集共享给插件使用
可卸载:
Collectible属性为 true 的 ALC 支持整体卸载类型同一性:不同 ALC 中加载的同类型,运行时视为不同类型
2.3 卸载条件
ALC 必须标记为可收集(
isCollectible: true)释放所有对插件对象的引用
释放 ALC 本身的引用
触发 GC 回收
三、项目整体架构设计
3.1 分层结构

3.2 设计原则
契约分离:接口与实现分离,主程序只依赖契约
单向依赖:插件依赖主程序契约,主程序不直接依赖插件
依赖注入友好:支持将插件服务注册到主程序 DI 容器
统一生命周期:插件加载、初始化、执行、卸载全流程管控
四、完整源码实现
4.1 插件契约层(PluginHost.Contracts)
IPlugin.cs

IPluginFactory.cs

4.2 插件加载核心层(PluginHost.Core)
PluginLoadContext.cs

PluginLoader.cs

PluginManager.cs

4.3 示例插件实现
HelloPlugin 项目
HelloPluginFactory.cs

HelloPlugin.cs

CalcPlugin 项目

4.4 主程序宿主(PluginHost.App)
Program.cs

五、项目构建与部署配置
5.1 插件项目关键配置
每个插件的 .csproj 文件需设置:

关键说明:
CopyLocalLockFileAssemblies=true:将 NuGet 依赖复制到输出目录<Private>false+<ExcludeAssets>runtime</ExcludeAssets>:契约程序集不随插件输出,由主程序共享
5.2 目录结构部署

六、高级特性扩展
6.1 插件发现机制

6.2 插件配置文件(plugin.json)

6.3 卸载验证

七、常见坑与最佳实践
7.1 典型陷阱
类型不匹配:不同 ALC 加载的同名称类型不可互转,必须通过共享契约接口交互
泄漏引用:事件订阅、静态变量、回调等会导致 ALC 无法卸载
依赖冲突:共享程序集版本不一致会引发加载异常
文件锁定:
LoadFromAssemblyPath会锁定文件,建议先加载到内存流
7.2 最佳实践
契约最小化:共享契约程序集尽量精简,减少依赖
工厂模式:通过工厂创建插件实例,避免直接反射创建
统一异常处理:插件执行必须包裹 try-catch,防止插件崩溃拖垮主程序
版本兼容:契约接口变更需考虑向后兼容
资源释放:插件实现
IDisposable或IAsyncDisposable,卸载前确保资源释放
7.3 性能优化
插件加载按需进行,避免启动时全部加载
频繁加载卸载的场景考虑插件池化
大型插件可考虑延迟加载依赖程序集
八、总结
基于 AssemblyLoadContext 的插件式架构为 .NET 应用提供了强大的动态扩展能力。通过合理的契约设计、加载隔离和生命周期管控,可以构建出高可扩展性、高稳定性的插件化系统。该架构在工业上位机、业务平台、工具软件等领域有极高的实用价值。
完整项目可直接基于上述代码搭建,目标框架建议使用 .NET 8 或 .NET 9,以获得最佳的 ALC 功能与性能表现。

夜雨聆风