将接口移至其他程序集后Activator.CreateInstance抛出异常
解决IPlugin类型加载兼容问题的方案
核心原因
旧插件的元数据里硬编码了依赖AssemblyA中的IPlugin类型,即便AssemblyB存在同命名空间的IPlugin,CLR仍会尝试从AssemblyA加载该类型。而AppDomain.TypeResolve未触发,是因为CLR判定AssemblyA已加载,只是找不到对应类型,不会触发类型解析事件。
可行解决方法
1. 保留AssemblyA并添加类型转发
在AssemblyA中加入类型转发特性,将IPlugin指向AssemblyB中的实现,旧插件请求AssemblyA的IPlugin时,CLR会自动转向AssemblyB:
[assembly: TypeForwardedTo(typeof(AssemblyB.IPlugin))]
注意:AssemblyA无需保留IPlugin的实现代码,仅需该转发特性,且需要引用AssemblyB。此方案无需修改旧插件,兼容性最强。
2. 利用AppDomain.AssemblyResolve事件替代TypeResolve
由于问题出在AssemblyA已加载但找不到目标类型,TypeResolve不会触发,改用AssemblyResolve事件,当CLR无法从AssemblyA加载类型时,手动返回AssemblyB实例:
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { var assemblyName = new AssemblyName(args.Name); // 匹配AssemblyA中IPlugin相关的类型请求 if (assemblyName.Name == "AssemblyA" && args.Name.Contains("IPlugin")) { return typeof(AssemblyB.IPlugin).Assembly; } return null; };
3. 手动修改插件的程序集引用(限可修改的插件)
- 有源码的插件:重新编译时将依赖切换为AssemblyB;
- 无源码的插件:使用IL编辑工具(如dnSpy)替换插件中对AssemblyA的IPlugin引用为AssemblyB,此方式风险较高,需充分测试。
4. 配置程序集绑定重定向
在应用配置文件(app.config/web.config)中添加重定向规则,将AssemblyA的请求导向AssemblyB:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="AssemblyA" publicKeyToken="你的程序集公钥令牌" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-当前AssemblyA版本" newVersion="AssemblyB的版本号" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
注意:若程序集为强命名,AssemblyA和AssemblyB需使用相同公钥令牌,否则重定向失效。
优先级推荐
优先使用类型转发方案,这是CLR原生支持的类型迁移机制,稳定且无需修改旧插件或额外复杂逻辑。
内容的提问来源于stack exchange,提问作者DiscoStu
相关产品推荐
相关产品推荐

