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

动态加载外部DLL时DI注册触发FileNotFoundException问题求助

解决方案

核心问题分析

当使用Microsoft.Extensions.DependencyInjection注册Service或IService时,CLR会立即尝试解析Service类型的元数据,而该类型依赖未加载的Library.DLL,此时AssemblyResolve事件尚未生效,因此抛出文件未找到异常。


配置层面的解决方案

1. 延迟服务实例化(推荐)

将服务注册改为工厂委托模式,避免在注册阶段触发Service类型的加载,直到第一次解析服务时才实例化(此时已完成Library.DLL的动态加载)。

修改注册代码:

// 移除直接注册Service的代码
// services.TryAddSingleton<Service>();

// 改用工厂委托延迟创建实例
services.TryAddSingleton<IService>(sp =>
{
    // 此代码块仅在第一次解析IService时执行,此时Library.DLL已加载
    return new AppName.Infrastructure.FeatureX.Service();
});

原理:DI容器在注册时仅存储委托逻辑,不会立即尝试解析Service类型,直到调用GetRequiredService<IService>()时才执行委托,此时AssemblyResolve已生效,可正确加载Library.DLL。

2. 反射式服务注册

通过字符串类型名反射获取Service类型,避免编译时的直接类型依赖,从而推迟Library.DLL的加载时机。

修改注册代码:

// 通过反射获取Service类型(需确保程序集名称正确)
var serviceImplType = Type.GetType("AppName.Infrastructure.FeatureX.Service, AppName.Infrastructure");

// 注册接口与实现类型
services.TryAddSingleton(typeof(AppName.Application.FeatureX.IService), serviceImplType);

原理:使用Type.GetType()时,CLR仅在需要创建实例时才会加载包含该类型的程序集及依赖的Library.DLL,此时AssemblyResolve事件已处理动态加载逻辑。

3. 拆分宿主构建流程

如果版本选择视图依赖DI,但可拆分宿主为轻量版和完整版:

  • 第一步:构建仅包含版本选择相关服务的轻量宿主(不依赖Library.DLL),显示版本选择视图并获取用户选定的路径。
  • 第二步:设置AssemblyResolve事件处理程序,动态加载选定版本的Library.DLL。
  • 第三步:构建完整宿主,注册所有依赖Library.DLL的服务。

示例流程:

// 1. 构建轻量宿主(仅包含版本选择ViewModel等无Library依赖的服务)
var lightHostBuilder = Host.CreateDefaultBuilder()
    .ConfigureServices(services =>
    {
        services.AddSingleton<VersionSelectionViewModel>();
    });
using var lightHost = lightHostBuilder.Build();

// 2. 显示版本选择视图,获取用户选择的Library路径
var vm = lightHost.Services.GetRequiredService<VersionSelectionViewModel>();
ShowVersionSelectionWindow(vm);
string selectedLibraryPath = vm.SelectedLibraryPath;

// 3. 设置AssemblyResolve事件
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var assemblyName = new AssemblyName(args.Name);
    if (assemblyName.Name == "Library.DLL")
    {
        return Assembly.LoadFrom(selectedLibraryPath);
    }
    return null;
};

// 4. 构建完整宿主,注册依赖Library的服务
var fullHostBuilder = Host.CreateDefaultBuilder()
    .ConfigureServices(services =>
    {
        services.TryAddSingleton<IService, Service>();
        // 其他服务注册...
    });
using var fullHost = fullHostBuilder.Build();

// 启动主应用逻辑
RunMainApplication(fullHost.Services);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:50:05