Похоже, что это можно решить с помощью украшения IHostedService
, хотя контейнер по умолчанию .Net Core IoC не поддерживает регистрацию декораторов, для этого есть простой обходной путь.
Вы можете создать декоратор для IHostedService
следующим образом:
public abstract class MyHostedServiceDecorator : IHostedService
{
private readonly MyHostedServiceDecorator _next;
protected MyHostedServiceDecorator(MyHostedServiceDecorator next)
{
_next = next;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
await StartAsyncInternal(cancellationToken);
if (_next != null)
{
await _next.StartAsync(cancellationToken);
}
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await StopAsyncInternal(cancellationToken);
if (_next != null)
{
await _next.StopAsync(cancellationToken);
}
}
protected abstract Task StartAsyncInternal(CancellationToken token);
protected abstract Task StopAsyncInternal(CancellationToken token);
}
Создайте столько декораторов, сколько вам нужно:
public class HostedServiceOneDecorator : MyHostedServiceDecorator
{
public HostedServiceOneDecorator(MyHostedServiceDecorator next) : base(next)
{
}
protected override async Task StartAsyncInternal(CancellationToken token)
{
Console.Write("This is my decorated start async!");
}
protected override async Task StopAsyncInternal(CancellationToken token)
{
Console.Write("This is my decorated stop async!");
}
}
В вашем зарегистрированном сервисном вызове на хостингедекоратор выглядит так:
public class MyHostedService : IHostedService
{
private readonly MyHostedServiceDecorator
_decorator;
public MyHostedService(MyHostedServiceDecorator decorator)
{
_decorator = decorator;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// base StartAsync logic ...
await _decorator.StartAsync(cancellationToken);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
// base StopAsync logic ...
await _decorator.StopAsync(cancellationToken);
}
}
И, наконец, вы регистрируете сервис и его декораторы, передавая следующий декоратор в предыдущий конструктор.
services.AddSingleton<IHostedService, MyHostedService>();
services.AddSingleton<MyHostedServiceDecorator>(
new HostedServiceOneDecorator(new HostedServiceTwoDecorator(/*etc*/)));
Все декораторы будут вызваны вЦепная мода, пока нет следующей!