Injecting Simple Injector components into IHostedService with ASP.NET Core 2.0

asked7 years ago
last updated7 years ago
viewed6.3k times
Up Vote12Down Vote

In ASP.NET Core 2.0, there is a way to add background tasks by implementing the IHostedService interface (see https://learn.microsoft.com/en-us/aspnet/core/fundamentals/hosted-services?view=aspnetcore-2.0). By following this tutorial, the way I was able to get it working was by registering it in the ASP.NET Core container. My goal is to be reading messages from a queue and processing the jobs in the background; a message is posted to the queue (via controller action) and then processed in the background on a timed interval.

// Not registered in SimpleInjector
services.AddSingleton<IHostedService, MyTimedService>();

When I put this registration in the ASP.NET Core container, it kicks off the process automatically on application startup. However, when I register this in SimpleInjector, the service is not automatically started. I believe this is the case because we only register the SimpleInjector container with the MvcControllers and MvcViewComponents:

// Wire up simple injector to the MVC components
container.RegisterMvcControllers(app);
container.RegisterMvcViewComponents(app);

The problem I run into is when I want to start injecting components register from SimpleInjector (e.g. Repositories, generic handlers with decorators...) into an implementation of IHostedService as demonstrated below:

public class TimedService : IHostedService, IDisposable
{
    private IJobRepository _repo;
    private Timer _timer;

    public TimedService(IJobRepository repo)
    {
        this._repo = repo;
    }
    ...
    ...
    ...
}

Since IHostedService is registered with ASP.NET Core and not Simple Injector, I receive the following error when running the timed background service:

Unhandled Exception: System.InvalidOperationException: Unable to resolve service for type 'Optimization.Core.Interfaces.IJobRepository' while attempting to activate 'Optimization.API.BackgroundServices.TimedService'.

So my question is, what is the best way to implement background tasks in Simple Injector? Does this require a separate integration package than the standard MVC integration? How am I able to inject my Simple Injector registrations into the IHostedService? If we could automatically start the service after being registered in Simple Injector, I think that would solve this problem.

Thank you for any pointers here and for any advice on this topic! I could be doing something wrong. I have really enjoyed using Simple Injector for the past year.