How can I use .net core's default dependency injection in Hangfire ?
I am new to Hangfire and searching for an example which works with asp.net core.
See full example on GitHub https://github.com/gonzigonz/HangfireCore-Example.
Live site at http://hangfirecore.azurewebsites.net/
Make sure you have the Core version of Hangfire:
dotnet add package Hangfire.AspNetCore
Configure your IoC by defining a JobActivator
. Below is the config for use with the default asp.net core container service:
public class HangfireActivator : Hangfire.JobActivator
{
private readonly IServiceProvider _serviceProvider;
public HangfireActivator(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public override object ActivateJob(Type type)
{
return _serviceProvider.GetService(type);
}
}
Next register hangfire as a service in the Startup.ConfigureServices
method:
services.AddHangfire(opt =>
opt.UseSqlServerStorage("Your Hangfire Connection string"));
Configure hangfire in the Startup.Configure
method. In relationship to your question, the key is to configure hangfire to use the new HangfireActivator
we just defined above. To do so you will have to provide hangfire with the IServiceProvider
and this can be achieved by just adding it to the list of parameters for the Configure
method. At runtime, DI will providing this service for you:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IServiceProvider serviceProvider)
{
...
// Configure hangfire to use the new JobActivator we defined.
GlobalConfiguration.Configuration
.UseActivator(new HangfireActivator(serviceProvider));
// The rest of the hangfire config as usual.
app.UseHangfireServer();
app.UseHangfireDashboard();
}
When you enqueue a job, use the registered type which usually is your interface. Don't use a concrete type unless you registered it that way. You must use the type registered with your IoC else Hangfire won't find it. For Example say you've registered the following services:
services.AddScoped<DbManager>();
services.AddScoped<IMyService, MyService>();
Then you could enqueue DbManager
with an instantiated version of the class:
BackgroundJob.Enqueue(() => dbManager.DoSomething());
However you could not do the same with MyService
. Enqueuing with an instantiated version would fail because DI would fail as only the interface is registered. In this case you would enqueue like this:
BackgroundJob.Enqueue<IMyService>( ms => ms.DoSomething());