This seems that it can be solved by decorating the IHostedService
, although .Net Core's default IoC container does not support registering decorators, there's an easy workaround for that.
You can create a decorator for the IHostedService
like this:
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);
}
Create as many decorators you need like:
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!");
}
}
In your registered hosted service call the decorator like this:
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);
}
}
And finally you register service and its decorators by passing the next decorator in the previous' constructor.
services.AddSingleton<IHostedService, MyHostedService>();
services.AddSingleton<MyHostedServiceDecorator>(
new HostedServiceOneDecorator(new HostedServiceTwoDecorator(/*etc*/)));
All the decorators will be called in a chain-like fashion until there is no next!