You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins环境下使用Mono.Cecil解析程序集失败问题求助

问题:Mono.Cecil在Jenkins执行单元测试时解析ASource程序集失败,本地运行正常

场景说明

解决方案包含三个程序集:

  • ASource:包含待测试类MyClass,该程序集引用了其他第三方/内部程序集
  • ATest:基于NUnit编写的单元测试项目,测试ASource中的MyClass
  • ATestUtils:引用Mono.Cecil,提供通过Type获取类型属性的工具方法

ATestUtils核心代码

// In ATestUtils
public static IEnumerable<PropertyDefinition> GetPropertiesFromType(Type typeOfClass)
{
    var ass = AssemblyDefinition.ReadAssembly(typeOfClass.Assembly.Location);
    var refs = ass.MainModule.ImportReference(typeOfClass);
    var typeDef = refs.Resolve();
    
    return typeDef.Properties;
}

错误信息

Jenkins执行测试时抛出异常:

Error : ATest.MyUnitTestClass.MyUnitTest

Mono.Cecil.AssemblyResolutionException : Failed to resolve assembly: 'ASource, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
   bei Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters) in C:\src\cecil\Mono.Cecil\BaseAssemblyResolver.cs:Zeile 122.
   bei Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name) in C:\src\cecil\Mono.Cecil\BaseAssemblyResolver.cs:Zeile 117.
   bei Mono.Cecil.DefaultAssemblyResolver.Resolve(AssemblyNameReference name) in C:\src\cecil\Mono.Cecil\DefaultAssemblyResolver.cs:Zeile 33.
   bei Mono.Cecil.MetadataResolver.Resolve(TypeReference type) in C:\src\cecil\Mono.Cecil\MetadataResolver.cs:Zeile 110.
   bei Mono.Cecil.ModuleDefinition.Resolve(TypeReference type) in C:\src\cecil\Mono.Cecil\ModuleDefinition.cs:Zeile 748.
   bei Mono.Cecil.TypeReference.Resolve() in C:\src\cecil\Mono.Cecil\TypeReference.cs:Zeile 280.
   bei ATestUtils.TestTools.GetPropertiesFromType(Type typeOfClass) in D:\Hudson\workspace\MyBranchName\MyProject\ATestUtils\TestTools.cs:Zeile 47.
   bei ATest.MyUnitTestClass.MyUnitTest()

已确认Jenkins环境中typeOfClass.Assembly.Location对应的ASource.dll文件存在,需解答:

  1. 是否因ASource依赖其他程序集导致加载失败?
  2. 若需加载依赖应如何操作?
  3. 为何本地运行正常?

环境信息

  • Visual Studio 2022 v17.6.3
  • Mono.Cecil v0.11.5
  • NUnit v3.13.3
  • NUnit3TestAdapter v4.5.0
  • Jenkins v2.401.1(Windows10.amd64),通过Pipeline脚本执行PowerShell命令,调用NUnit.Console 3.12.0和opencover.4.7.1221

解答

1. 是否因ASource依赖其他程序集导致加载失败?

是。Mono.Cecil的默认解析器在尝试解析类型时,需要找到ASource的所有依赖程序集。本地环境中,依赖程序集通常和ASource.dll在同一输出目录,或已被GAC、系统路径缓存;但Jenkins的构建输出结构可能不同,依赖程序集不在Mono.Cecil默认搜索路径内,导致解析ASource时无法找到其依赖,进而抛出异常。

2. 如何正确加载依赖程序集?

需要给Mono.Cecil的DefaultAssemblyResolver添加ASource及其依赖所在的目录,让解析器能找到所有需要的程序集。修改后的代码如下:

public static IEnumerable<PropertyDefinition> GetPropertiesFromType(Type typeOfClass)
{
    var assemblyPath = typeOfClass.Assembly.Location;
    var assemblyDir = Path.GetDirectoryName(assemblyPath);
    
    // 创建自定义解析器,添加依赖目录
    var resolver = new DefaultAssemblyResolver();
    resolver.AddSearchDirectory(assemblyDir);
    
    // 读取程序集时指定解析器
    var readerParams = new ReaderParameters
    {
        AssemblyResolver = resolver,
        ReadWrite = false
    };
    
    var ass = AssemblyDefinition.ReadAssembly(assemblyPath, readerParams);
    var typeDef = ass.MainModule.GetType(typeOfClass.FullName);
    
    // 直接从当前模块获取类型定义,避免额外解析步骤
    return typeDef?.Properties ?? Enumerable.Empty<PropertyDefinition>();
}

关键修改点:

  • 显式创建DefaultAssemblyResolver,并添加ASource所在目录到搜索路径,确保依赖程序集能被找到
  • 读取程序集时传入包含自定义解析器的ReaderParameters
  • 直接通过MainModule.GetType获取类型定义,避免ImportReference+Resolve的额外解析步骤,减少依赖解析触发的概率

如果ASource的依赖分散在多个目录,可通过resolver.AddSearchDirectory()逐个添加这些目录。

3. 为何本地运行正常?

本地运行时,Visual Studio的测试运行环境会将所有依赖程序集复制到测试输出目录(如bin/Debug),ASource.dll和它的依赖在同一目录下;同时本地系统的GAC、环境变量PATH可能包含依赖程序集的路径,Mono.Cecil的默认解析器能自动找到这些位置的程序集。

而Jenkins环境中可能存在以下差异:

  • 构建脚本未将ASource的依赖程序集复制到测试执行目录
  • Jenkins工作目录结构与本地不同,依赖程序集不在默认搜索路径内
  • OpenCover或NUnit.Console的执行上下文,程序集搜索路径与本地Visual Studio测试环境不一致

内容的提问来源于stack exchange,提问作者BNB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 03:53:14