Есть несколько способов приблизиться к этому. Простейший способ, вероятно, состоит в том, чтобы соединить размещенный сервис по кроссовому соединению таким образом, чтобы встроенная система конфигурации разрешала размещенный сервис из Simple Injector:
// Register in Simple Injector as Singleton
container.RegisterSingleton<THostedService>();
// Cross-wire TimedService in the built-in configuration system
services.AddSingleton<IHostedService>(
c => container.GetInstance<TimedService>());
Обратите внимание, что размещенные службы разрешаются только один раз и кешируются навсегда, что делает их по сути одиночными. Вот почему вы должны зарегистрировать его в Simple Injector как Singleton.
Следствием этого, однако, является то, что вы не сможете внедрить какие-либо Scoped
или Transient
зависимости в вашу размещенную службу. Кроме того, он заставляет ваш компонент приложения (TimedService
) зависеть от абстракции ядра ASP.NET (IHostedService
). Это не идеально.
Поэтому мой предпочтительный подход состоит в том, чтобы вместо этого создать реализацию адаптера, которую вы регистрируете в системе конфигурации ASP.NET Core, которая перенаправляет вызовы Simple Injector, используя абстракцию для конкретного приложения для реализации вашего сервиса. Таким образом, вместо создания многих IHostedService
реализаций, вы определяете абстракцию, которая является специфической и идеальной для вашего приложения. Давайте назовем эту абстракцию IMyJob
.
Реализация адаптера IHostedService
может выглядеть следующим образом:
public class SimpleInjectorJobProcessorHostedService : IHostedService, IDisposable
{
private readonly Container container;
private Timer timer;
public SimpleInjectorJobProcessorHostedService(Container c) => this.container = c;
public Task StartAsync(CancellationToken cancellationToken)
{
this.timer = new Timer(this.DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
return Task.CompletedTask;
}
private void DoWork(object state)
{
// Run operation in a scope
using (AsyncScopedLifestyle.BeginScope(this.container))
{
// Resolve the collection of IMyJob implementations
foreach (var service in this.container.GetAllInstances<IMyJob>())
{
service.DoWork();
}
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
this.timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose() => this.timer?.Dispose();
}
Вы можете зарегистрировать его в ядре ASP.NET следующим образом:
services.AddSingleton<IHostedService>(
new SimpleInjectorJobProcessorHostedService(container));
Таким образом, фактические выполняемые вами задания могут не учитываться в ASP.NET Core и могут быть определены следующим образом:
public class CoolJob : IMyJob
{
private readonly IJobRepository repo;
public CoolJob(IJobRepository repo) => this.repo = repo;
public void DoWork() => ...
}
И все задания могут быть зарегистрированы в Simple Injector следующим образом:
// NOTE: Simple Injector v4.3 API
container.Collection.Register<IMyJob>(typeof(CoolJob).Assembly);