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

Simple Injector CrossWiring使用困惑与问题咨询

Simple Injector跨接线与原生DI兼容问题解决方案

你的场景完全可行,Simple Injector专门设计了与Microsoft.Extensions.DependencyInjection(MSDI)的集成方案,用于封装类库的高级DI功能(装饰器、条件注册等)给原生DI用户使用。你遇到的两个问题本质是双向配置不完整和服务注册可见性缺失,以下是针对性解决方案:


问题1:IServiceProvider无法解析Simple Injector注册的App

原因

App仅注册在Simple Injector容器中,MSDI的ServiceProvider对该类型完全不知情,自然无法解析。只有服务被注册到IServiceCollection后,MSDI才能识别并处理。

解决方案

在ConfigureServices中,将App注册到MSDI,但委托Simple Injector容器创建实例:

.ConfigureServices((hostBuilderContext, services) =>
{
    container.RegisterSingleton<App>();

    services.AddSingleton<ISaySomethingService, SaySomethingService>();
    services.AddSimpleInjector(container);

    // 新增:把Simple Injector中的App桥接到MSDI
    services.AddSingleton<App>(sp => sp.GetRequiredService<Container>().GetInstance<App>());
})

修改后,调用host.Services.GetRequiredService<App>()时,MSDI会委托Simple Injector创建实例,同时依赖链(如App依赖的ISaySomethingService)可通过跨接线正常解析。


问题2:添加options.AddLogging()后跨接线服务无法获取ILogger

原因

错误信息显示MSDI无法解析ILogger,核心问题:

  1. MSDI默认仅注册泛型日志接口ILogger<T>,而非非泛型ILogger
  2. 你的SaySomethingService构造函数依赖的是ILogger,而非推荐的ILogger<SaySomethingService>
  3. 启用Simple Injector的AddLogging()后,跨接线服务仍由MSDI创建,但MSDI中无ILogger注册

解决方案

有两种可选方式:

方式1:改用泛型日志接口(推荐)

修改SaySomethingService的构造函数依赖为ILogger<SaySomethingService>:

public class SaySomethingService : ISaySomethingService
{
    private readonly ILogger<SaySomethingService> _logger;

    public SaySomethingService(ILogger<SaySomethingService> logger)
    {
        _logger = logger;
    }

    // 其他业务代码
}

这是MSDI日志系统的标准用法,无需额外配置。

方式2:注册非泛型ILogger(兼容旧代码)

若必须保留非泛型ILogger依赖,在ConfigureServices中添加:

services.AddSingleton<ILogger>(sp => 
    sp.GetRequiredService<ILoggerFactory>().CreateLogger("Default"));

这样MSDI就能解析非泛型ILogger,跨接线服务可正常创建。


类库封装适配方案(核心需求落地)

针对「类库用Simple Injector实现高级DI功能,让原生DI开发者无感知调用」的场景,正确的封装方式如下:

1. 类库中编写扩展方法,封装Simple Injector逻辑

public static class MyLibraryServiceCollectionExtensions
{
    public static IServiceCollection AddMyLibrary(this IServiceCollection services)
    {
        // 创建并配置Simple Injector容器
        var container = new Container
        {
            Options = { DefaultScopedLifestyle = new AsyncScopedLifestyle() }
        };

        // 注册类库内部服务(含装饰器、条件注册等)
        container.RegisterSingleton<App>();
        // 示例:添加装饰器
        // container.RegisterDecorator<ISaySomethingService, LoggingSaySomethingDecorator>();

        // 集成MSDI并自动处理跨接线
        services.AddSimpleInjector(container, options =>
        {
            options.AddLogging();
            options.CrossWireServices = true; // 自动跨接线MSDI服务到Simple Injector
        });

        // 将类库对外服务桥接到MSDI,让原生DI可直接解析
        services.AddSingleton<App>(sp => sp.GetRequiredService<Container>().GetInstance<App>());
        // 其他对外服务同理注册

        // 验证Simple Injector配置(开发环境建议启用)
        container.Verify();

        return services;
    }
}

2. 主应用调用方式(开发者无需关心Simple Injector)

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // 开发者只需调用类库扩展方法
        services.AddMyLibrary();
        // 开发者仍可正常注册自己的MSDI服务
        services.AddSingleton<ISaySomethingService, SaySomethingService>();
    })
    .Build();

// 直接通过IServiceProvider解析类库服务
var app = host.Services.GetRequiredService<App>();
await app.Run();

关键注意事项

  • 双向可见性:类库对外暴露的服务必须同时注册到MSDI(委托Simple Injector创建),否则原生DI无法解析。
  • 跨接线时机:使用Simple Injector的官方集成扩展AddSimpleInjector自动处理跨接线,避免手动操作的时机问题。
  • 日志兼容:优先使用ILogger<T>,减少额外配置成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:15:30