Nec*_*ras 5 c# dependency-injection simple-injector asp.net-core
我试图创建所描述的,这将作为Windows服务运行的服务在这里。我的问题是示例 Web 主机服务构造函数只接受一个IWebHost参数。我的服务需要一个更像这样的构造函数:
public static class HostExtensions
{
public static void RunAsMyService(this IWebHost host)
{
var webHostService =
new MyService(host, loggerFactory, myClientFactory, schedulerProvider);
ServiceBase.Run(webHostService);
}
}
Run Code Online (Sandbox Code Playgroud)
我的Startup.cs文件看起来类似于:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.AddInMemoryCollection();
this.Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
this.container.RegisterSingleton<IConfiguration>(this.Configuration);
services.AddSingleton<IControllerActivator>(
new SimpleInjectorControllerActivator(container));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseSimpleInjectorAspNetRequestScoping(this.container);
this.container.Options.DefaultScopedLifestyle = new AspNetRequestLifestyle();
this.InitializeContainer(app, loggerFactory);
this.container.Verify();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
}
private void InitializeContainer(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
container.Register(() => loggerFactory, Lifestyle.Singleton);
container.Register<IMyClientFactory>(() => new MyClientFactory());
container.Register<ISchedulerProvider>(() => new SchedulerProvider());
}
Run Code Online (Sandbox Code Playgroud)
显然,我使用 Simple Injector 作为 DI 容器。它IServiceCollection在他们的文档中详细注册。
我的问题是如何访问 HostExtensions 类中的框架容器(IServicesCollection),以便将必要的依赖项注入到MyService? 对于 MVC 控制器,这一切都只是在幕后处理,但我不知道任何详细说明如何在其他地方需要的地方访问它的文档。
您只需对代码进行一些小的调整即可使其正常工作。
Container字段:public staticStartuppublic class Startup
{
public static readonly Container container = new Container();
Run Code Online (Sandbox Code Playgroud)
Startup并移入Main:Startup这样做允许在类完成之后但在应用程序实际启动之前将额外的注册添加到容器中:
public static void Main(string[] args)
{
...
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(directoryPath)
.UseStartup<Startup>()
.Build();
// Don't forget to remove the Verify() call from within the Startup.
Startup.Container.Verify();
...
}
Run Code Online (Sandbox Code Playgroud)
MyService为单身人士在容器中将其显式注册为单例允许简单注入器对其运行诊断,并防止MyService可能意外拥有的意外强制依赖项。您应该将其注册为单例,因为它将在应用程序期间保持活动状态:
public static void Main(string[] args)
{
...
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(directoryPath)
.UseStartup<Startup>()
.Build();
Startup.Container.RegisterSingleton<MyService>();
Startup.Container.Verify();
...
}
Run Code Online (Sandbox Code Playgroud)
MyService所需的缺失依赖项。MyService依赖于host、loggerFactory、myClientFactory和schedulerProvider,目前这些都没有注册。
可以在方法host内注册Main:
public static void Main(string[] args)
{
...
Startup.Container.RegisterSingleton<MyService>();
Startup.Container.RegisterSingleton<IWebHost>(host);
Startup.Container.Verify();
...
}
Run Code Online (Sandbox Code Playgroud)
虽然loggerFactory可以在类中注册Startup:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
Container.RegisterSingleton(loggerFactory);
...
}
Run Code Online (Sandbox Code Playgroud)
我假设myClientFactory和schedulerProvider依赖项已经在容器中注册。
RunAsMyService扩展方法替换为容器中的简单解析由于MyService已成功在容器中注册及其所有依赖项,我们现在应该能够从容器中解析它并将其传递给方法ServiceBase.Run:
public static void Main(string[] args)
{
...
Startup.Container.Verify();
ServiceBase.Run(Startup.Container.GetInstance<MyService>());
}
Run Code Online (Sandbox Code Playgroud)
这应该就是全部了。
最后一点,根据您正在构建的应用程序的类型,您可能Startup根本不需要如此复杂的类。您可以将容器的配置移至更靠近方法的位置Main。您是否应该这样做,取决于您实际需要多少。
这是一个不上课的例子Startup:
public static void Main(string[] args)
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new AspNetRequestLifestyle();
IWebHost host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.ConfigureServices(services =>
{
// Configure framework components
services.AddOptions();
})
.Configure(app =>
{
app.UseSimpleInjectorAspNetRequestScoping(container);
// Apply cross-wirings:
container.RegisterSingleton(
app.ApplicationServices.GetRequiredService<ILoggerFactory>());
})
.UseStartup<Startup>()
.Build();
container.RegisterSingleton<MyService>();
container.RegisterSingleton(host);
container.Verify();
ServiceBase.Run(Startup.Container.GetInstance<MyService>());
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3424 次 |
| 最近记录: |