Assembly.Load 不适合插件化架构,应使用 AssemblyLoadContext(.NET 5+ 推荐)或 Assembly.LoadFrom(.NET Framework),配合共享接口契约实现动态加载、调用与卸载。

在 C# 中实现插件化架构,核心在于动态加载和调用外部程序集(.dll),Assembly.Load 是最基础的方式之一,但它**并不适合插件场景**——因为它只能加载已存在于 AppDomain.CurrentDomain.AssemblyResolve 路径(如 bin 目录)或 GAC 中的程序集,且无法卸载,也不支持从任意路径加载。
真正适用于插件系统的,是 AssemblyLoadContext(.NET Core/.NET 5+ 推荐)或 Assembly.LoadFrom / Assembly.LoadFile(.NET Framework 传统方式),配合接口抽象与反射调用。下面分关键点说明:
✅ 插件必须基于契约(接口)设计
主程序与插件不能直接依赖对方的具体类型,需定义共享的接口类库(如 IPlugin.cs),供双方引用:
- 主程序只引用接口项目,不引用任何插件实现
- 每个插件项目引用同一份接口,并实现其方法(如
Execute()、GetName()) - 编译后插件为独立 .dll,放在指定目录(如
./plugins/)
✅ 动态加载插件:推荐用 AssemblyLoadContext(.NET 5+)
它支持隔离加载、显式卸载(避免内存泄漏),是现代插件系统的首选:
- 新建自定义上下文:
class PluginLoadContext : AssemblyLoadContext { ... },重写Load方法返回null表示不委托给默认上下文 - 加载插件:
var context = new PluginLoadContext(pluginPath); var assembly = context.LoadFromAssemblyPath(pluginPath); - 查找并创建插件实例:
var pluginType = assembly.GetTypes().FirstOrDefault(t => t.GetInterfaces().Contains(typeof(IPlugin))); var plugin = Activator.CreateInstance(pluginType) as IPlugin; - 使用完后调用
context.Unload()卸载整个上下文(注意:.NET 6+ 才完全支持异步卸载)
⚠️ Assembly.Load 不适用于插件
Assembly.Load("MyPlugin") 只按简单名称查找,依赖自动绑定机制,实际会去 GAC 或当前应用目录找,且一旦加载就无法卸载;Assembly.Load(AssemblyName) 同理,不适合运行时未知路径的插件。
mallcloud商城基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba并采用前后端分离vue的企业级微服务敏捷开发系统架构。并引入组件化的思想实现高内聚低耦合,项目代码简洁注释丰富上手容易,适合学习和企业中使用。真正实现了基于RBAC、jwt和oauth2的无状态统一权限认证的解决方案,面向互联网设计同时适合B端和C端用户,支持CI/CD多环境部署,并提
如果你看到代码里写了 Assembly.Load 做插件加载,基本是误用——它解决的是“已知强名称、已部署好”的内部程序集引用问题,不是插件热插拔。
✅ 简单兼容方案(.NET Framework 或快速验证)
若暂不能升级到 .NET 5+,可用 Assembly.LoadFrom(path):
- 能从任意文件路径加载 .dll,并解析其依赖(自动搜索同目录)
- 但无法卸载单个程序集,整个 AppDomain 卸载才释放(所以通常不重启就无法更新插件)
- 使用前建议检查
Assembly.GetAssembly(typeof(IPlugin))是否已加载,避免重复加载同名程序集引发异常
基本上就这些。插件化不复杂,但容易忽略上下文隔离和卸载机制——选对加载方式,再配上清晰的接口契约,就能稳稳支撑模块扩展。









