簡體   English   中英

ASP.NET Core 不會用 StructureMap 替換 IoC

[英]ASP.NET Core does not replace IoC with StructureMap

我的應用程序基於 ASP.NET Core 2.1 和 .NET Core 2.1(從 2.2 降級)通用主機作為 Windows 服務。 因此, IHostBuilder首先與其他服務和框架一起啟動,然后(如果角色允許)使用IWebHostBuilder和所有WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().StartAsync()在頂部啟動 Web 服務。 二級 WebHost 是另一回事; 它已初始化並工作,但我還沒有檢查 IoC 替換是否與通用主機有相同的問題。

現在,通用主機初始化:

new HostBuilder().ConfigureServices((hostContext, services) =>
{
    services.AddHostedService<LifetimeService>(); // Gets launched when host is up
    var container = ContainerBuilder.BuildBaseContainer(services, new WorkingPath());
    services.AddSingleton<IContainer>(container);
    services.AddStructureMap(); // Has no effect
});

IContainer 初始化:

public static Container BuildBaseContainer(IServiceCollection services, IWorkingPath workingPath)
{
    var container = new Container();
    container.Configure(config =>
    {
        config.Scan(scan =>
        {
            workingPath.OwnLoadedAssemblies.Where(asm => !asm.IsDynamic).ForEach(scan.Assembly);
            scan.LookForRegistries();
            scan.AddAllTypesOf<IPlatformService>();
        });
        config.For<IContainer>().Use(() => container);                
        config.Populate(services);
    });
    container.AssertConfigurationIsValid();
    return container;
}

問題就在這里,在該注冊托管服務(或其他任何地方)的構造函數中

public LifetimeService(IEnumerable<IPlatformService> services,
                       IServiceProvider sp, IContainer c)
{
    var inCollection = services.Any();
    var inContainer = c.TryGetInstance<IPlatformService>() != default;
    var inProvider = sp.GetRequiredService<IPlatformService>() != default;
}

ps:IServiceProvider 和 IContainer 僅用於演示目的,我只需要“服務”

LifetimeServicecontainer.AssertConfigurationIsValid()期間初始化時,我得到
inCollection為真
inContainer為真
inProvider為真
IServiceProviderStructureMapServiceProvider

實際LifetimeService執行表明
inCollection是假的
inContainer為真
inProvider是假的
IServiceProviderServiceProviderEngineScope

我不打算將 IServiceProvider 或 IContainer 傳遞給構造函數,但似乎使用 IServiceProvider 而不是 IContainer 來解決依賴關系,並且我得到了空值。 sp.GetRequiredService<IContainer>().TryGetInstance<IPlatformService>()這樣愚蠢的事情確實有效。
有一些使用 WebHost 和 Startup 類的快樂路徑示例,其中注入應該正常工作。 似乎與通用主機無關……它可能有一天會取代 WebHost,但鮮為人知且未廣泛使用。 嗯,也可能是由於 .NET Core 版本降級,但不太可能。 我還嘗試在 ConfigureServices() 期間從 IContainer 替換 IServiceProvider 和 IServiceScopeFactory ,但沒有運氣。 我的想法是將內部容器替換或轉發到 StructureMap。 我可能誤解了它應該如何工作......

有沒有人成功地嘗試“結合”通用主機和外部 IoC?

我已經解開了謎題! 最后,根據一個過於簡化的示例( https://github.com/aspnet/Hosting/blob/master/samples/GenericHostSample/ProgramFullControl.cs ),我不得不將HostBuilder初始化更改為

new HostBuilder()
.UseServiceProviderFactory(new StructureMapContainerFactory(workingPath))
.ConfigureServices((hostContext, services) =>
{                   
    services.AddHostedService<LifetimeService>();
});

並介紹提供者工廠本身

public class StructureMapContainerFactory : IServiceProviderFactory<IContainer>
{
    private readonly IWorkingPath workingPath;
    // pass any dependencies to your factory
    public StructureMapContainerFactory(IWorkingPath workingPath)
    {
        this.workingPath = workingPath;
    }

    public IContainer CreateBuilder(IServiceCollection services)
    {
        services.AddStructureMap();
        return ContainerBuilder.BuildBaseContainer(services, workingPath);
    }

    public IServiceProvider CreateServiceProvider(IContainer containerBuilder)
    {
        return containerBuilder.GetInstance<IServiceProvider>();
    }
}

現在內部容器被 StructureMap 替換,並且LifetimeService解析的IServiceProviderStructureMapServiceProvider類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM