我在ASP.net核心(2.2)应用程序中的基于内存的Hangfire(1.6.21)中使用。在Startup.cs
中,我将服务配置为单例:
services.AddSingleton<IXXXService, XXXService>(); // In ConfigureServices(...)
并使用以下几行启动Hangfire:
app.UseHangfireServer(); // In Configure(...)
这是XXXService
的简化代码:
public class XXXService : IXXXService
{
public ExternalAPIService()
{
Console.WriteLine("xxx");
}
public void QueueRequest(Guid requestId)
{
BackgroundJob.Enqueue(() => this.AnalyzeRequest(requestId));
}
public async Task AnalyzeRequest(Guid requestId)
{
Console.WriteLine("Analyzing request...");
}
}
问题在于,尽管XXXService
被定义为一个单例,并且实际上仅通过连续请求创建了一次,但最终调用AnalyzeRequest
时,它由hangfire重新创建。如何路由hangfire以使用由ASP的默认DI管理的单例对象?
答案 0 :(得分:1)
我发现我必须执行以下操作。
首先,我们告诉作业需要使用什么服务。注意这里我们给它提供接口。
BackgroundJob.Enqueue<IService>(service => service.Method(param));
根据建议,我们需要为Hangfire使用的JobActivator添加替代。 Hangfire接受该表达式,并知道它需要实现IService的服务,因此我们只需要告诉它如何获取它即可。
接下来,我们需要创建一个JobActivator,如下所示:
public class ServiceProviderActivator : JobActivator
{
private IServiceProvider _serviceProvider;
public ServiceProviderActivator(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public override object ActivateJob(Type jobType)
{
return _serviceProvider.GetService(jobType);
}
}
现在,当Hangfire尝试运行作业时,它将需要IService并使用服务提供商。现在剩下的就是为它提供您的应用所使用的相同服务提供商。
在启动文件中的ConfigureServices中:
services.AddHangfire((serviceProvider, configuration) =>
{
// other configuration
configuration.UseActivator(new ServiceProviderActivator(serviceProvider));
});
答案 1 :(得分:0)
您可以创建一个使用IoC来解决依赖关系的JobActivator,因此它将始终使用单例类。
这是一个例子: https://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html