.NET运行时程序集绑定重定向:如何强制插件使用新版类库
问题根本原因
CLR 在默认应用程序域中对程序集的加载行为是「一旦加载就无法卸载」,且对于程序集标识(名称+版本+公钥Token)匹配的程序集,会优先使用首次加载的版本。你之前尝试的操作无效核心原因如下:
AutoGenerateBindingRedirects和GenerateBindingRedirectsOutputType仅作用于编译期生成的绑定重定向配置,对运行时动态加载的程序集不生效- 引用的
SpecificVersion属性是编译期校验逻辑,不影响运行时程序集解析规则 AssemblyResolve事件仅在 CLR 无法根据标识找到对应程序集时才会触发,旧版类库已加载且标识匹配的前提下,不会触发该事件
方案1:使用独立应用程序域(适用于 .NET Framework 场景)
这是隔离性最稳定的解决方案,实现步骤:
- 每次加载插件B和对应依赖类库时,单独创建一个新的
AppDomain实例 - 将类库、插件B都加载到这个独立的应用程序域中,插件启动类需要继承
MarshalByRefObject以支持跨域调用 - 需要更新类库时,直接调用
Unload方法卸载旧的应用程序域,再创建新的域加载新版类库和新的插件B即可,不同域的程序集完全隔离,不会出现版本混用问题
方案2:使用可回收程序集加载上下文(适用于 .NET Core/.NET 5+ 场景)
比应用程序域更轻量的运行时隔离方案:
- 创建标记为
Collectible = true的自定义AssemblyLoadContext实例 - 所有动态加载的类库、插件B都通过这个自定义上下文加载,不要使用默认的全局加载上下文
- 需要更新类库时,调用自定义上下文的
Unload()方法释放所有相关程序集,再创建新的上下文加载新版类库和插件B,不同上下文的程序集解析完全独立,不会复用旧版本
方案3:强制修改程序集标识触发重解析(不推荐,仅用于无法调整隔离逻辑的场景)
如果必须在默认应用程序域中完成加载,可通过修改程序集标识让CLR主动触发重解析:
- 给依赖类库添加强名称签名,每次发布新版本时升级程序集版本号
- 加载新版类库后,手动配置运行时绑定重定向规则,强制所有对旧版本类库的请求指向新版;也可以在
AssemblyResolve事件中判断请求的类库名称,直接返回你新加载的新版实例即可
内容的提问来源于stack exchange,提问作者Kliment Nechaev
相关产品推荐
相关产品推荐

