我们正在开发运行.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容器中注入它?
答案 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();