Hangfire依赖项注入生存期范围 [英] Hangfire dependency injection lifetime scope

查看:173
本文介绍了Hangfire依赖项注入生存期范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在重写整个问题,因为我知道原因,但仍需要解决方案:

I'm rewriting this entire question because I realize the cause, but still need a solution:

我在Hangfire中有一个定期执行的工作,它每分钟运行一次并检查数据库,可能会更新一些内容,然后退出.

I have a recurring job in Hangfire that runs every minute and check the database, possibly updates some stuff, then exits.

我将dbcontext注入到包含job方法的类中.我注册此dbcontext以便使用以下命令注入

I inject my dbcontext into the class containing the job method. I register this dbcontext to get injected using the following

builder.RegisterType<ApplicationDbContext>().As<ApplicationDbContext>().InstancePerLifetimeScope();

但是,似乎每次执行作业时Hangfire都不会创建单独的生存期范围,因为构造函数只被调用一次,尽管作业方法每分钟被调用一次.

However, it seems that Hangfire does not create a seperate lifetime scope every time the job runs, because the constructor only gets called once, although the job method get's called every minute.

这给我带来了问题.如果用户更新了数据库中的某些值(dbcontext被注入到其他地方,并用于更新值),则仍在使用的上下文Hangfire开始返回已更改的过时值.

This causes issues for me. If the user updates some values in the database (dbcontext gets injected somewhere else, and used to update values), the context still being used Hangfire starts returning out-dated values that have already been changed.

推荐答案

Hangfire当前为每个Worker使用共享实例JobActivator,它们使用以下方法来解决依赖关系:

Hangfire currently uses a shared Instance of JobActivator for every Worker, which are using the following method for resolving a dependency:

    public override object ActivateJob(Type jobType)

计划为 Milestone 2.0.0 向此方法添加JobActivationContext.

It is planned to add a JobActivationContext to this method for Milestone 2.0.0.

就目前而言,还没有办法说出解决依赖关系的工作.我想解决此问题的唯一方法是利用作业在不同线程上串行运行的事实(我不知道AutoFac,所以我以Unity为例).

For now, there is no way to say for which job a dependency gets resolved. The only way I can think of to workaround this issue would be to use the fact that jobs are running serial on different threads (I don't know AutoFac so I use Unity as an example).

您可以创建一个JobActivator,每个线程可以存储单独的作用域:

You could create a JobActivator that can store separate scopes per thread:

public class UnityJobActivator : JobActivator
{
    [ThreadStatic]
    private static IUnityContainer childContainer;

    public UnityJobActivator(IUnityContainer container)
    {
        // Register dependencies
        container.RegisterType<MyService>(new HierarchicalLifetimeManager());

        Container = container;
    }

    public IUnityContainer Container { get; set; }

    public override object ActivateJob(Type jobType)
    {
        return childContainer.Resolve(jobType);
    }

    public void CreateChildContainer()
    {
        childContainer = Container.CreateChildContainer();
    }

    public void DisposeChildContainer()
    {
        childContainer.Dispose();
        childContainer = null;
    }
}

IServerFilter实现中使用JobFilter来为每个作业(线程)设置此作用域:

Use a JobFilter with IServerFilter implementation to set this scope for every job (thread):

public class ChildContainerPerJobFilterAttribute : JobFilterAttribute, IServerFilter
{
    public ChildContainerPerJobFilterAttribute(UnityJobActivator unityJobActivator)
    {
        UnityJobActivator = unityJobActivator;
    }

    public UnityJobActivator UnityJobActivator { get; set; }

    public void OnPerformed(PerformedContext filterContext)
    {
        UnityJobActivator.DisposeChildContainer();
    }

    public void OnPerforming(PerformingContext filterContext)
    {
        UnityJobActivator.CreateChildContainer();
    }
}

最后设置您的DI:

UnityJobActivator unityJobActivator = new UnityJobActivator(new UnityContainer());
JobActivator.Current = unityJobActivator;

GlobalJobFilters.Filters.Add(new ChildContainerPerJobFilterAttribute(unityJobActivator));

这篇关于Hangfire依赖项注入生存期范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆