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

.NET 6框架扩展:反射查找IRegisterDI类失败与AppDomain问题

解决.NET 6中自动扫描第三方扩展程序集的问题

问题根源

.NET默认采用延迟加载程序集的机制:只有当程序集中的类型被实际调用(比如实例化、访问静态成员)时,CLR才会将该程序集加载到当前AppDomain中。你遇到的情况就是因为第三方程序集未被主动引用,所以没被加载,导致AppDomain.CurrentDomain.GetAssemblies()找不到对应的类型。

解决方案

1. 主动扫描应用目录下的所有程序集

直接遍历应用输出目录中的所有.dll文件,手动加载并扫描目标类型:

using System.Reflection;
using System.Runtime.Loader;

var appRootDir = AppContext.BaseDirectory;
// 获取目录下所有.dll文件
var assemblyPaths = Directory.GetFiles(appRootDir, "*.dll", SearchOption.TopDirectoryOnly);

var registrationTypes = new List<Type>();

foreach (var path in assemblyPaths)
{
    try
    {
        // 使用AssemblyLoadContext加载程序集(.NET Core+推荐方式)
        var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
        
        // 筛选实现IRegisterDI的非接口、非抽象类
        var types = assembly.GetTypes()
            .Where(t => typeof(IRegisterDI).IsAssignableFrom(t) 
                        && !t.IsInterface 
                        && !t.IsAbstract);
        
        registrationTypes.AddRange(types);
    }
    catch (BadImageFormatException)
    {
        // 跳过非.NET程序集(比如原生DLL)
        continue;
    }
    catch (Exception ex)
    {
        // 处理其他加载异常,比如日志记录
        Console.WriteLine($"加载程序集{Path.GetFileName(path)}失败:{ex.Message}");
    }
}

2. 优化类型匹配逻辑

不要仅通过接口名称判断,直接使用类型比较可以避免同名接口的冲突问题:

// 替换原有的名称匹配逻辑
.Where(tp => typeof(IRegisterDI).IsAssignableFrom(tp) && !tp.IsInterface && !tp.IsAbstract)

3. 可选:通过配置指定要扫描的程序集

如果不想扫描所有.dll,可以通过配置文件指定需要加载的第三方程序集名称,缩小扫描范围:

// appsettings.json
{
  "ExtensionAssemblies": [
    "ThirdParty.EchoService.dll",
    "AnotherExtension.dll"
  ]
}

然后加载时只处理配置中的程序集:

var config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

var targetAssemblies = config.GetSection("ExtensionAssemblies").Get<string[]>();

foreach (var assemblyName in targetAssemblies)
{
    var path = Path.Combine(appRootDir, assemblyName);
    if (File.Exists(path))
    {
        // 加载并扫描逻辑同上
    }
}

注意事项

  • 确保第三方NuGet包的程序集被复制到输出目录:在NuGet包的项目中,设置<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>,确保程序集被复制到消费应用的输出目录。
  • 避免重复加载程序集:可以缓存已加载的程序集,防止重复扫描同一程序集。
  • 处理依赖问题:如果第三方程序集依赖其他未加载的程序集,可能需要额外处理依赖加载逻辑。

内容的提问来源于stack exchange,提问作者Trevor.Screws

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:40:25