Comment utiliser l'injection de dépendance par défaut de .net core dans Hangfire?
Je suis nouveau sur Hangfire et cherche un exemple qui fonctionne avec asp.net core.
Voir l'exemple complet sur GitHub https://github.com/gonzigonz/HangfireCore-Example .
Site en direct sur le site http://hangfirecore.azurewebsites.net/
Assurez-vous de disposer de la version Core de Hangfire:dotnet add package Hangfire.AspNetCore
Configurez votre IoC en définissant un JobActivator
. Vous trouverez ci-dessous la configuration à utiliser avec le service de conteneur principal asp.net par défaut:
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);
}
}
Ensuite, enregistrez Hangfire en tant que service dans le Startup.ConfigureServices
méthode:
services.AddHangfire(opt =>
opt.UseSqlServerStorage("Your Hangfire Connection string"));
Configurez hangfire dans le Startup.Configure
méthode. En relation avec votre question, la touche permet de configurer Hangfire pour utiliser le nouveau HangfireActivator
que nous venons de définir ci-dessus. Pour ce faire, vous devrez fournir à hangfire le IServiceProvider
. Pour ce faire, ajoutez-le simplement à la liste des paramètres de la méthode Configure
. Au moment de l'exécution, DI vous fournira ce service:
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();
}
Lorsque vous mettez un travail en file d'attente, utilisez le type enregistré, qui correspond généralement à votre interface. N'utilisez pas de type concret sauf si vous l'avez enregistré de cette façon. Vous devez utiliser le type enregistré auprès de votre IoC, sinon Hangfire ne le trouvera pas. Par exemple déclarez que vous avez enregistré les services suivants:
services.AddScoped<DbManager>();
services.AddScoped<IMyService, MyService>();
Ensuite, vous pouvez mettre en file d'attente DbManager
avec une version instanciée de la classe:
BackgroundJob.Enqueue(() => dbManager.DoSomething());
Cependant, vous ne pourriez pas faire la même chose avec MyService
. La mise en file d'attente avec une version instanciée échouerait, car DI échouerait car seule l'interface est enregistrée. Dans ce cas, vous devriez mettre en file d'attente comme ceci:
BackgroundJob.Enqueue<IMyService>( ms => ms.DoSomething());
Autant que je sache, vous pouvez utiliser l'injection de dépendance de cœurs .net de la même manière que pour tout autre service.
Vous pouvez utiliser un service contenant les travaux à exécuter, qui peut être exécuté comme suit.
var jobId = BackgroundJob.Enqueue(x => x.SomeTask(passParamIfYouWish));
Voici un exemple de la classe Job Service
public class JobService : IJobService
{
private IClientService _clientService;
private INodeServices _nodeServices;
//Constructor
public JobService(IClientService clientService, INodeServices nodeServices)
{
_clientService = clientService;
_nodeServices = nodeServices;
}
//Some task to execute
public async Task SomeTask(Guid subject)
{
// Do some job here
Client client = _clientService.FindUserBySubject(subject);
}
}
Et dans vos projets Startup.cs, vous pouvez ajouter une dépendance comme d'habitude
services.AddTransient< IClientService, ClientService>();
Pas sûr que cela réponde à votre question ou pas
La réponse de DoritoBandito est incomplète ou obsolète.
public class EmailSender { public EmailSender(IDbContext dbContext, IEmailService emailService) { _dbContext = dbContext; _emailService = emailService; } }
Enregistrer les services:
services.AddTransient<IDbContext, TestDbContext>(); services.AddTransient<IEmailService, EmailService>();
En file d'attente:
BackgroundJob.Enqueue<EmailSender>(x => x.Send(13, "Hello!"));
Source: http://docs.hangfire.io/en/latest/background-methods/passing-dependencies.html
Je devais démarrer HangFire dans la fonction principale. Voici comment je l'ai résolu:
public static void Main(string[] args)
{
var Host = CreateWebHostBuilder(args).Build();
using (var serviceScope = Host.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
try
{
var liveDataHelper = services.GetRequiredService<ILiveDataHelper>();
var justInitHangfire = services.GetRequiredService<IBackgroundJobClient>();
//This was causing an exception (HangFire is not initialized)
RecurringJob.AddOrUpdate(() => liveDataHelper.RePopulateAllConfigDataAsync(), Cron.Daily());
// Use the context here
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "Can't start " + nameof(LiveDataHelper));
}
}
Host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
Si vous essayez de configurer rapidement Hangfire avec ASP.NET Core (testé dans ASP.NET Core 2.2), vous pouvez également utiliser Hangfire.MemoryStorage . Toute la configuration peut être effectuée dans Startup.cs
:
using Hangfire;
using Hangfire.MemoryStorage;
public void ConfigureServices(IServiceCollection services)
{
services.AddHangfire(opt => opt.UseMemoryStorage());
JobStorage.Current = new MemoryStorage();
}
protected void StartHangFireJobs(IApplicationBuilder app, IServiceProvider serviceProvider)
{
app.UseHangfireServer();
app.UseHangfireDashboard();
//TODO: move cron expressions to appsettings.json
RecurringJob.AddOrUpdate<SomeJobService>(
x => x.DoWork(),
"* * * * *");
RecurringJob.AddOrUpdate<OtherJobService>(
x => x.DoWork(),
"0 */2 * * *");
}
public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
StartHangFireJobs(app, serviceProvider)
}
Bien sûr, tout est stocké en mémoire et il est perdu une fois le pool d'applications recyclé, mais c'est un moyen rapide de voir que tout fonctionne comme prévu avec une configuration minimale.
Pour passer à la persistance de la base de données SQL Server, vous devez installer Hangfire.SqlServer
package et configurez-le simplement à la place de la mémoire:
services.AddHangfire(opt => opt.UseSqlServerStorage(Configuration.GetConnectionString("Default")));
Actuellement, Hangfire est profondément intégré à Asp.Net Core. Installez Hangfire.AspNetCore sur configurez le tableau de bord et intégrez l'intégration à la DI. Ensuite, il vous suffit de définir vos dépendances à l'aide du noyau ASP.NET, comme d'habitude.