在ASP.NET Core C#中使用hangfire时,多次构造Singleton服务

时间:2019-02-19 10:06:18

标签: c# asp.net-core hangfire

我在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管理的单例对象?

2 个答案:

答案 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