将HostBuilder.ConfigureServices与DryIoc容器一起使用?

时间:2018-08-16 08:14:05

标签: c# .net-core dryioc microsoft.extensions.hosting

我有一些类库为我创建的应用程序提供服务,并且由于遗留原因,它们与DryIoc紧密绑定。也就是说,服务注册是紧密绑定的,而不是实际的服务。

如果可以的话,我宁愿不去修改那些代码,如果不需要的话。

创建一个新的ASP.NET MVC Core应用程序,我可以通过更改ConfigureServices方法以返回IServiceProvider来使用DryIoc:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc().AddControllersAsServices();

    var container = new Container().WithDependencyInjectionAdapter(services);
    return container.ConfigureServiceProvider<CompositionRoot>();
}

(这是来自内存,因此可能不是100%正确,但这并不重要)

重要的变化是可以将void方法更改为返回IServiceProvider可以返回的DryIoc

但是,对于我想用于控制台应用程序,后台服务等的HostBuilder,配置服务的方法不接受IServiceProvider,所以我不确定该怎么做

重要的代码是这样:

var builder = new HostBuilder()
    .ConfigureAppConfiguration((hostingContext, config) => { ... })
    .ConfigureServices((hostContext, services) =>
    {
        services.AddOptions();
        // configure services
    })
    .ConfigureLogging((hostingContext, logging) => { ... });

上面的ConfigureServices方法有一个重载和一个扩展方法:

  • ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
  • ConfigureServices(this IHostBuilder hostBuilder, Action<IServiceCollection> configureDelegate)

在这方面,似乎没有任何关于返回或使用IServiceProviderDryIoc可以为我提供的任何其他规定。

这可能吗?有没有办法弥合差距?还是只需要对类库使用Microsoft IServiceCollection?由于它们已在许多项目中使用,因此我不想因为在特定情况下看起来最简单而就进行更改,但如果需要的话,我必须这样做。

1 个答案:

答案 0 :(得分:3)

@Nkosi提供了一个错误的答案(但在ASP.NET应用程序的上下文中是正确的),并且注释线程引发了关于方法UseServiceProviderFactory的讨论。是解决方案,谢谢大家。

要使用UseServiceProviderFactory,我必须自己实现一个类,并在项目中添加适当的nuget包引用。

以下是步骤:

  1. 添加对DryIoc.dll的引用(毫不奇怪)
  2. 添加对DryIoc.Microsoft.DependencyInjection的引用
  3. 更改注册码
  4. 提供UseServiceProviderFactory所需的框架的自定义实现

原始代码如下:

var builder = new HostBuilder()
    .ConfigureAppConfiguration((hostingContext, config) => { ... })
    .ConfigureServices((hostContext, services) =>
    {
        services.AddOptions();
        // configure services
    })
    .ConfigureLogging((hostingContext, logging) => { ... });

以下是替代方法:

var builder = new HostBuilder()
    .ConfigureAppConfiguration((hostingContext, config) => { ... })
    .ConfigureServices((hostContext, services) =>
    {
        services.AddOptions();
        // configure services
    })

    //////////////////// ADD THIS vvvvvvvv
    .UseServiceProviderFactory(new DryIocServiceProviderFactory())
    .ConfigureContainer<Container>((hostContext, container) =>
    {
        container.Register<...>();
    })
    //////////////////// ADD THIS ^^^^^^^^


    .ConfigureLogging((hostingContext, logging) => { ... });

然后提供DryIocServiceProviderFactory的此实现:

internal class DryIocServiceProviderFactory : IServiceProviderFactory<IContainer>
{
    public IContainer CreateBuilder(IServiceCollection services)
        => new Container().WithDependencyInjectionAdapter(services);

    public IServiceProvider CreateServiceProvider(IContainer containerBuilder)
        => containerBuilder.ConfigureServiceProvider<CompositionRoot>();
}

上面的CompositionRoot类在配置过程中已解决,并且可以使用构造函数来配置容器。可以使用不执行任何操作的虚拟类。