Взаимодействие зависимостей Hangfire с ядром .net
Как я могу использовать инъекцию зависимостей ядра ядра .net в Hangfire?
Я новичок в Hangfire и ищу пример, который работает с ядром asp.net.
Ответы
Ответ 1
Смотрите полный пример на GitHub https://github.com/gonzigonz/HangfireCore-Example.
Живой сайт по адресу http://hangfirecore.azurewebsites.net/
-
Убедитесь, что у вас есть базовая версия Hangfire:
dotnet add package Hangfire.AspNetCore
-
Настройте свой IoC, определив JobActivator
. Ниже приведена конфигурация для использования со стандартной службой ядра контейнера asp.net:
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);
}
}
-
Затем зарегистрируйте hangfire как службу в методе Startup.ConfigureServices
:
services.AddHangfire(opt =>
opt.UseSqlServerStorage("Your Hangfire Connection string"));
-
Настройка замедленного воспламенения в Startup.Configure
методе. В связи с вашим вопросом, ключ заключается в том, чтобы настроить Hangfire для использования нового HangfireActivator
мы только что определили выше. Для этого вам нужно будет предоставить hangfire с IServiceProvider
и этого можно достичь, просто добавив его в список параметров для метода Configure
. Во время выполнения DI предоставит вам эту услугу:
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();
}
-
Когда вы ставите задачу в очередь, используйте зарегистрированный тип, который обычно является вашим интерфейсом. Не используйте конкретный тип, если вы не зарегистрировали его таким образом. Вы должны использовать тип, зарегистрированный в вашем IoC, иначе Hangfire не найдет его. Например, скажем, вы зарегистрировали следующие услуги:
services.AddScoped<DbManager>();
services.AddScoped<IMyService, MyService>();
Затем вы можете поставить в очередь DbManager
с DbManager
инстанцированной версией класса:
BackgroundJob.Enqueue(() => dbManager.DoSomething());
Однако вы не можете сделать то же самое с MyService
. Постановка в очередь с инстанцированной версией не удалась бы, потому что DI потерпел бы неудачу, поскольку зарегистрирован только интерфейс. В этом случае вы бы поставили в очередь вот так:
BackgroundJob.Enqueue<IMyService>( ms => ms.DoSomething());
Ответ 2
Насколько мне известно, вы можете использовать инъекцию зависимостей ядра .net так же, как и для любой другой службы.
Вы можете использовать сервис, который содержит выполняемые задания, которые могут выполняться так
var jobId = BackgroundJob.Enqueue(x => x.SomeTask(passParamIfYouWish));
Ниже приведен пример класса 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);
}
}
И в ваших проектах Startup.cs вы можете добавить зависимость как обычно
services.AddTransient< IClientService, ClientService>();
Не уверен, что это отвечает на ваш вопрос или нет.
Ответ 3
DoritoBandito ответ неполный или не рекомендуется.
public class EmailSender {
public EmailSender(IDbContext dbContext, IEmailService emailService)
{
_dbContext = dbContext;
_emailService = emailService;
}
}
Регистрация услуг:
services.AddTransient<IDbContext, TestDbContext>();
services.AddTransient<IEmailService, EmailService>();
Ставить:
BackgroundJob.Enqueue<EmailSender>(x => x.Send(13, "Hello!"));
Источник: http://docs.hangfire.io/en/latest/background-methods/passing-dependencies.html
Ответ 4
В настоящее время Hangfire тесно интегрирован с Asp.Net Core. Установите Hangfire.AspNetCore для автоматической настройки панели мониторинга и интеграции DI. Затем вам просто нужно определить свои зависимости, используя ядро ASP.NET, как всегда.
Ответ 5
Мне пришлось запустить HangFire в основной функции. Вот как я это решил:
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>();
}
Ответ 6
Если вы пытаетесь быстро настроить Hangfire с помощью ASP.NET Core (протестировано в ASP.NET Core 2.2), вы также можете использовать Hangfire.MemoryStorage. Все настройки можно выполнить в 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)
}
Конечно, все хранится в памяти и теряется после перезапуска пула приложений, но это быстрый способ увидеть, что все работает, как ожидается, с минимальной конфигурацией.
Чтобы переключиться на постоянство базы данных SQL Server, вы должны установить пакет Hangfire.SqlServer
и просто настроить его вместо хранения в памяти:
services.AddHangfire(opt => opt.UseSqlServerStorage(Configuration.GetConnectionString("Default")));