遇到反射时找不到依赖程序集的问题

今天在一个 ASP.NET Core 7.0 的项目中遇到反射时 Could not load file or assembly 的问题,build 时没问题,运行时出现下面的异常

System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types.
Could not load file or assembly 'Cnblogs.Architecture.Ddd.EventBus.Abstractions, Version=13.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.Assembly.GetTypes()

对应的反射代码如下

protected virtual IEnumerable<IZzkApplication> GetZzkApplications()
{
    return AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(p => p.GetTypes())
        .Where(p => typeof(IZzkApplication).IsAssignableFrom(p))
        .Where(p => p.IsClass && !p.IsAbstract)
        .Select(Activator.CreateInstance)
        .Cast<IZzkApplication>()
        .Where(a => a.Name != "ing");
}

添加排查问题的临时代码,打印出反射时所加载的 Cnblogs 名称开头的所有程序集

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
    if (assembly.FullName.Contains("Cnblogs", StringComparison.OrdinalIgnoreCase))
    {
        Console.WriteLine(assembly.FullName);
        foreach (var refAssembly in assembly.GetReferencedAssemblies())
        {
            if (refAssembly.FullName.Contains("Cnblogs", StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine("  -- " + refAssembly.FullName);
            }
        }
    }
}

发现找不到的程序集是 Cnblogs.UCenter.DTO 程序集所依赖的

Cnblogs.UCenter.DTO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null
  -- Cnblogs.Architecture.Ddd.EventBus.Abstractions, Version=13.0.0.0, Culture=neutral, PublicKeyToken=null

Cnblogs.UCenter.DTO 来自于2层 nuget 包引用,引用关系见下图(来自Visual Studio 2022)

Cnblogs.UCenter.DTO 通过 nuget 包引用了 Cnblogs.Architecture.Ddd.EventBus.Abstractions

<PackageReference Include="Cnblogs.Architecture.Ddd.EventBus.Abstractions" Version="13.0.0" />

为什么上面的引用关系图中没有出现这层引用关系呢?因为 Cnblogs.UCenter.ServiceAgent 没有通过 nuget 包引用 Cnblogs.UCenter.DTO,而是通过 project reference 进行引用, Cnblogs.UCenter.DTO 在打包时包含了 Cnblogs.UCenter.DTO 程序集,这种打包方式详见博文 .NET Core NuGet 多项目套餐打包的正确姿势,通过这次问题也知道了这种另类打包方式的一个弊端。

对于 "Could not load file or assembly" 问题的解决方法很简单,当前项目直接安装对应的 nuget 包。这个问题的麻烦之处在于 build 时不能发现,运行时才出现。

dotnet add package Cnblogs.Architecture.Ddd.EventBus.Abstractions
posted @ 2023-02-03 15:06  dudu  阅读(683)  评论(0编辑  收藏  举报