.NET Core 2.x中与HostBuilder的简单注入器集成

时间:2018-09-19 16:12:37

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

我们正在开发运行.net core 2.x的Windows服务。在史蒂夫·戈登(Steve Gordon)发表running .netcore generic host applications as a service的博客帖子之后,只要我们使用IServiceCollection,一切似乎就可以很好地进行。我更喜欢SimpleInjector,但不确定如何像在asp.net核心中那样使用它。我有一种方法可以代替Default service container replacement所述的内置DI,并且我知道SI团队不推荐这种方法ASP.NET Core MVC Integration Guide,因此在此用例中是否有更好的方法?

这是我到目前为止所拥有的,但不舒服

-主程序

internal class Program
{
    private static async Task Main(string[] args)
    {
        var isService = !(Debugger.IsAttached || args.Contains("--console"));

        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Runner>();
                //configure SimpleInjector here???
            });

        if (isService)
        {
            await builder.RunAsServiceAsync();
        }
        else
        {
            await builder.RunConsoleAsync();
        }
    }
}

在此处配置容器的工作原理或多或少,但是由主机创建的第一个类(在这种情况下为Runner)由主机创建,并通过IServicesCollection注入所有依赖项。所以我的问题是如何从SI容器中注入它?

3 个答案:

答案 0 :(得分:1)

最明显的答案是……没有任何依赖项注入Runner中。相反,Runner是代表您的应用程序入口点的类,因此我在此处配置我的容器,并在Runner停止时处置它。跑步者的完整代码...

public class Runner : IHostedService, IDisposable
{
    private Container _container;
    public Runner()
    {
        _container = new Container();
        _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        Bootstrapper.Bootstrap(_container);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _container.Dispose();
        _container = null;
    }
}

答案 1 :(得分:0)

我会钩上HostBuilder的ConfigureContainer方法并在那里设置simpleinjectore,就像这样:

                   HostBuilder()
                   .ConfigureServices((hostContext, services) =>
                   {
                       services.AddLogging();
                       services.AddOptions();
                   })

虽然确实可以使用IHostedService实现,但我认为它可能隐藏正在发生的事情。我相信基础架构自举应该在一个地方完成,或者至少在一个地方精心策划。我认为容器是基础架构,可以通过HostBuilder方法将其与应用程序的其余部分一起设置。

一个附加的优势还可能是您不完全替换ServiceCollection,因为它可以很好地完成其他与框架相关的事情。我仍将使用ServiceCollection做一些事情的例子:

https://postman-echo.com/response-headers?foo1=bar1&access-control-allow-origin=*

这与simpleinjector文档中有关使用ASP.NET Core设置容器的说明一致:

  

Simple Injector的实践是使用Simple Injector构建应用程序组件的对象图,并让内置容器构建框架和第三方组件。SimpleInjector的实践是使用Simple Injector进行构建应用程序组件的对象图,并让内置容器构建框架和第三方组件

.net核心和通用HostBuilder也应如此。

答案 2 :(得分:0)

通用主机从服务集合中解析托管服务,因此解决方案是在Simple Injector中注册托管服务,然后从Simple Injector解析它们以在Services集合中注册:

var container = new Container();
var host = new HostBuilder()
//...
    .ConfigureServices((context, services) =>
    {
        container.Collection.Append(typeof(IHostedService), typeof(Runner));
        services.AddSingleton(_ => container.GetAllInstances<IHostedService>());
    })
//...
    .Build();

container.Verify();
await host.RunAsync();