Hangfire在.NET Core中的DI作用域范围是什么?

8
假设在ASP.NET Core中,我像下面这样注册一个被称为Scoped的依赖项:
IServiceCollection services = ...
services.AddScoped<IEmailService, EmailService>();

我知道每个HTTP请求都会创建一个新的作用域(scope),并且将重复使用电子邮件(Email)服务的新实例。此外,同一作用域(scope)将在请求的生命周期内保持不变。

现在,想象我添加了一个Hangfire后台作业,如下所示:

RecurringJob.AddOrUpdate<IServiceA>("DoA", s => s.DoA(), Cron.Daily());

where

public class ServiceA: IServiceA {
    public ServiceA(IEmailService emailService) { ... }
    public void DoA() { ... }
}

我想了解在hangfire作业术语中,scoped是什么意思,默认情况下,hangfire是否会:

  • 为所有作业和运行使用一个范围
  • 为每个作业创建单独的范围,但同一个作业的不同运行共享范围
  • 为任何作业的每次运行都创建单独的范围

额外加分:如何配置它。


查询归结为“Hangfire是否生成作用域,还是我必须显式地执行它”?鉴于Hangfire服务可以无限期运行,#1和#2将毫无意义,实际上就像单例一样。 - Panagiotis Kanavos
6
如果您在DI配置中简单地调用AddHangFire,似乎已经默认提供了这个功能。每个执行都会被包装在一个作用域中,无论使用什么DI容器。尽管如此,这一点还没有被记录在任何地方。 - Panagiotis Kanavos
谢谢,我很乐意接受这个作为答案。 - eddyP23
2个回答

2
正文:
正如Panagiotis Kanavos在上面的评论中提到的(但为了更明显地作为已接受的答案):
“如果您只需在DI配置中调用AddHangFire,看起来这是开箱即用的。每个执行都会包装在作用域中,无论使用什么DI容器。尽管这并没有在任何地方得到记录。”

我看到了一些奇怪的缓存行为,这可能表明其他情况,需要验证实现。 - Poul K. Sørensen
可以确认它没有使用 Microsoft 范围。创建的范围与 Hangfire JobActivator 相关联,而不是 MS DI。 - Poul K. Sørensen
我错了,有一个dotnet core范围处理-但是我感觉DbContext被缓存了。FindAsync从上下文返回值,而不是最新的数据库值,就像它在多个作业运行中被缓存一样。 - Poul K. Sørensen
@PoulK.Sørensen,你有没有找到解决方法?我在使用作用域资源和Hangfire时遇到了一些有趣的行为,所以我很想知道是否变得太麻烦,你只能使用其他依赖注入框架(例如Windsor)。 - mochsner

0
请查看这里的实现: https://github.com/HangfireIO/Hangfire/blob/7eb4b3fd56abe8eeed692265aff39e2d694e86df/src/Hangfire.Core/Server/CoreBackgroundJobPerformer.cs#L47
using (var scope = _activator.BeginScope(context))
        {
            object instance = null;

            if (context.BackgroundJob.Job == null)
            {
                throw new InvalidOperationException("Can't perform a background job with a null job.");
            }
            
            if (!context.BackgroundJob.Job.Method.IsStatic)
            {
                instance = scope.Resolve(context.BackgroundJob.Job.Type);

                if (instance == null)
                {
                    throw new InvalidOperationException(
                        $"JobActivator returned NULL instance of the '{context.BackgroundJob.Job.Type}' type.");
                }
            }

            var arguments = SubstituteArguments(context);
            var result = InvokeMethod(context, instance, arguments);

            return result;
        }

Hangfire在解析您的类之前创建一个作用域,这意味着您可以像在ASP.net中那样使用和配置作用域实例在您的依赖容器中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接