Comment puis-je utiliser l'injection de dépendances par défaut de .NET Core dans Hangfire ?
Je suis nouveau sur Hangfire et je cherche un exemple qui fonctionne avec ASP.NET Core.
Comment puis-je utiliser l'injection de dépendances par défaut de .NET Core dans Hangfire ?
Je suis nouveau sur Hangfire et je cherche un exemple qui fonctionne avec ASP.NET Core.
Voir l'exemple complet sur GitHub https://github.com/gonzigonz/HangfireCore-Example .
Site en direct à http://hangfirecore.azurewebsites.net/
Assurez-vous que vous avez la version Core de Hangfire :dotnet add package Hangfire.AspNetCore
Configurez votre IoC en définissant un JobActivator
. Voici la configuration à utiliser avec le service conteneur asp.net core 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 la section Startup.ConfigureServices
méthode :
services.AddHangfire(opt =>
opt.UseSqlServerStorage("Your Hangfire Connection string"));
Configurer hangfire dans le Startup.Configure
méthode. Pour répondre à votre question, le clé est de configurer hangfire pour utiliser la nouvelle HangfireActivator
que nous venons de définir ci-dessus. Pour ce faire, vous devrez fournir à hangfire l'information suivante IServiceProvider
et cela peut être réalisé en l'ajoutant simplement à la liste des paramètres de l'option Configure
méthode. Au moment de l'exécution, DI fournira ce service pour vous :
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 est généralement votre interface. N'utilisez pas un type concret, sauf si vous l'avez enregistré de cette façon. Vous devez utiliser le type enregistré avec votre IoC, sinon Hangfire ne le trouvera pas. Par exemple dites que vous avez enregistré les services suivants :
services.AddScoped<DbManager>();
services.AddScoped<IMyService, MyService>();
Vous pourriez alors mettre en file d'attente DbManager
avec une version instanciée de la classe :
BackgroundJob.Enqueue(() => dbManager.DoSomething());
Cependant, vous ne pouvez pas faire la même chose avec MyService
. La mise en file d'attente d'une version instanciée échouerait parce que le DI échouerait car seule l'interface est enregistrée. Dans ce cas, la mise en file d'attente se fait de la manière suivante :
BackgroundJob.Enqueue<IMyService>( ms => ms.DoSomething());
Il convient de noter que dans le ms => ms.DoSomething()
Dans ce cas, l'expression debe appeler une méthode sur le paramètre passé. Vous ne pouvez pas faire ms => Foo.StaticMethod(ms)
; Hangfire donne une exception cryptique dans ce cas.
La version actuelle de Hangfire (1.6.19) enregistre automatiquement AspNetCoreJobActivator. github.com/HangfireIO/Hangfire/blob/master/src/
De plus, les méthodes d'extension ne fonctionnent pas avec Hangfire. Il faut créer un wrapper.
La réponse de DoritoBandito est incomplète ou dépréciée.
public class EmailSender { public EmailSender(IDbContext dbContext, IEmailService emailService) { _dbContext = dbContext; _emailService = emailService; } }
Services de registre :
services.AddTransient<IDbContext, TestDbContext>(); services.AddTransient<IEmailService, EmailService>();
Enqueue :
BackgroundJob.Enqueue<EmailSender>(x => x.Send(13, "Hello!"));
Source : http://docs.hangfire.io/en/latest/background-methods/passing-dependencies.html
Pour autant que je sache, vous pouvez utiliser l'injection de dépendance des noyaux .net comme vous le feriez pour n'importe quel autre service.
Vous pouvez utiliser un service qui contient les tâches à 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 votre projet Startup.cs vous pouvez ajouter une dépendance comme d'habitude
services.AddTransient< IClientService, ClientService>();
Je ne suis pas sûr que cela réponde à votre question
J'ai également eu des dépendances qui ont été résolues dès le départ sans mettre en œuvre JobActivator
Actuellement, Hangfire est profondément intégré à Asp.Net Core. Installer Hangfire.AspNetCore a configuration du tableau de bord et l'intégration DI automatiquement. Ensuite, il vous suffit de définir vos dépendances en utilisant ASP.NET core comme toujours.
J'ai dû lancer HangFire dans la fonction principale. Voici comment j'ai résolu le problème :
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>();
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.