Hangfire依赖注入生命周期范围

par*_*ent 19 c# autofac hangfire

我正在重写整个问题因为我意识到原因,但仍然需要一个解决方案:

我在Hangfire中有一个经常性的工作,每分钟运行并检查数据库,可能更新一些东西,然后退出.

我将dbcontext注入包含job方法的类中.我注册这个dbcontext以使用以下注入

builder.RegisterType<ApplicationDbContext>().As<ApplicationDbContext>().InstancePerLifetimeScope();
Run Code Online (Sandbox Code Playgroud)

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

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

Dre*_*sel 18

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

    public override object ActivateJob(Type jobType)
Run Code Online (Sandbox Code Playgroud)

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

目前,没有办法说出依赖项得到解决的工作.我可以想到解决这个问题的唯一方法是使用作业在不同线程上运行串行的事实(我不知道AutoFac所以我以Unity为例).

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后设置您的DI:

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

GlobalJobFilters.Filters.Add(new ChildContainerPerJobFilterAttribute(unityJobActivator));
Run Code Online (Sandbox Code Playgroud)


Mil*_*hev 5

我们在Hangfire.Autofac中创建了一个新的拉取请求,其中包含Dresel描述的工作.希望它在主分支中合并:

https://github.com/HangfireIO/Hangfire.Autofac/pull/4