C#强名称程序集引用弱名称程序集游戏正常但NUnit测试加载失败
问题根因说明
你遇到的报错本质是不同版本.NET Framework的强名称验证规则差异:
- 游戏运行在.NET Framework 3.5环境,该版本CLR默认允许强名称程序集引用未签名的弱名称程序集,因此强名称的Utilities.dll加载弱名称的GameEngine.dll没有问题
- 单元测试运行在.NET Framework 4.0环境,该版本对强名称程序集的依赖签名验证规则收紧,默认要求强名称程序集引用的所有依赖项也必须是强签名的,因此Utilities.dll尝试加载未签名的GameEngine.dll时触发异常
单元测试可执行解决方案
- 方案1:修改单元测试项目的配置,关闭强名称验证限制
在ModUnitTests.dll的App.config文件中添加以下配置,即可兼容4.0环境下强名称程序集引用弱名称依赖的场景:
你也可以通过强名称工具跳过指定程序集的验证,执行命令:<configuration> <runtime> <bypassTrustedAppStrongNames enabled="true" /> </runtime> </configuration>sn -Vr *,<Utilities.dll的公钥Token>,该方案无需修改项目配置,仅对当前开发环境生效。 - 方案2:将单元测试项目的.NET Framework版本降级为3.5
与游戏运行环境保持一致,完全规避版本带来的规则差异,同时测试结果更贴合Mod实际运行的真实场景,需注意使用支持.NET Framework 3.5的NUnit版本即可正常运行。 - 方案3:按场景切换Utilities.dll的签名配置
在项目中新增单独的发布编译配置,仅在编译发布到游戏环境的版本时开启Utilities.dll的强名称签名,单元测试和本地调试阶段使用未签名的弱名称版本,可通过修改项目的.csproj文件,按编译条件设置强名称签名开关实现。
规避强名称问题的静态类链接复用方案
如果希望彻底避免强名称相关的兼容问题,可以改用以下代码复用方案,同样可实现多Mod同进程多版本共存:
- 共享项目(Shared Project)复用
将Utilities的代码从独立类库项目改为共享项目,所有Mod项目直接引用该共享项目,编译时Utilities的代码会直接嵌入到对应Mod的程序集中,无外部DLL依赖,天然不存在版本冲突问题,每个Mod使用的Utilities版本完全独立。 - ILMerge静态合并
编译Mod完成后,使用ILMerge工具将Mod.dll和对应版本的Utilities.dll合并为单个程序集,命令参考:ilmerge /out:ModFinal.dll Mod.dll Utilities.dll,合并后的程序集不需要附带独立的Utilities.dll,也不会和其他Mod的工具库版本产生冲突。 - 自定义依赖加载逻辑
取消Utilities.dll的强名称配置,每个Mod在自己的目录下存放对应版本的Utilities.dll,在Mod的初始化逻辑中注册AppDomain.CurrentDomain.AssemblyResolve事件,优先从Mod自身所在目录加载依赖项,即可实现同进程下不同Mod加载各自版本的Utilities.dll,无DLL冲突问题。
内容的提问来源于stack exchange,提问作者James Picone
相关产品推荐
相关产品推荐

