How to inject a reference to a specific IHostedService implementation?
Turns out there's an easy way to do this (thanks for the pointer, Steven).
If you need to be able to inject / get a reference to some service, go ahead and register the service normally (without worrying about any IHostedService
stuff):
services.AddSingleton<ServiceBusListener>();
Now we can register a separate hosted service whose only responsibility is to start/stop the service we just registered:
services.AddHostedService<BackgroundServiceStarter<ServiceBusListener>>();
Where BackgroundServiceStarter
is a helper class that looks something like:
public class BackgroundServiceStarter<T> : IHostedService where T:IHostedService
{
readonly T backgroundService;
public BackgroundServiceStarter(T backgroundService)
{
this.backgroundService = backgroundService;
}
public Task StartAsync(CancellationToken cancellationToken)
{
return backgroundService.StartAsync(cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken)
{
return backgroundService.StopAsync(cancellationToken);
}
}
Update 2018/8/6: updated code to avoid service locator pattern thanks to a suggestion from ygoe
Based on your answers, I made a helpful extension method. It allows to register an IHostedService
with another interface.
The other interface doesn't need to implement IHostedService
, so you don't expose the StartAsync()
and StopAsync()
methods
public static class ServiceCollectionUtils
{
public static void AddHostedService<TService, TImplementation>(this IServiceCollection services)
where TService : class
where TImplementation : class, IHostedService, TService
{
services.AddSingleton<TService, TImplementation>();
services.AddHostedService<HostedServiceWrapper<TService>>();
}
private class HostedServiceWrapper<TService> : IHostedService
{
private readonly IHostedService _hostedService;
public HostedServiceWrapper(TService hostedService)
{
_hostedService = (IHostedService)hostedService;
}
public Task StartAsync(CancellationToken cancellationToken)
{
return _hostedService.StartAsync(cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken)
{
return _hostedService.StopAsync(cancellationToken);
}
}
}