Hangfire定时任务与依赖注入

5

当使用RecurringJob调度运行时,Hangfire是否可以使用配置的JobActivator实例化对象呢?

该方法的签名似乎只强制使用静态:

public static void AddOrUpdate<T>(
    string recurringJobId,
    Expression<Action<T>> methodCall,

我有几个想法可以“滥用”静态方法来在后台传递信息,但我感觉可能会漏掉一些东西。Hangfire只支持在计划任务中使用静态方法是出于设计决策吗?

2个回答

21

不确定何时添加,但我在当前项目中刚刚执行了类似的操作,并且它可以正常工作。 EmailBackgroundTask是一个非静态类,而这是一个非静态方法。该类通过Hangfire.Unity DI包注入了4个依赖项。

RecurringJob.AddOrUpdate<EmailBackgroundTask>(x=>x.SendPeriodicEmail(),Cron.MinuteInterval(5));

1
我不确定在这个问题提出时是否已经有了被接受的答案,但现在应该接受这个答案。 - N8ALL3N
这并不使用依赖注入系统,它只是提供了一个作为泛型参数提到的类型的默认实例。正如文档中所述(https://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html),像@Steve一样实现JobActivator才是真正的解决方案。 - Stephane
2
当前(1.7.27)版本支持asp.net核心依赖注入,无需添加JobActivator等,只需在启动时添加AddHangfire()即可。像上面的示例一样编写代码,Hangfire将注入任何构造函数依赖项以创建EmailBackgroundTask。如果您使用不同的DI容器,则可能需要执行其他操作。 - Rory

1
快速回答是不行的, 默认的作业激活器只能在没有参数的构造函数或静态方法上工作。我做了一些(用VB.net)快速而简单的事情,以查看是否可以使其正常工作,并将其显示如下。
通过使用“AddOrUpdate”,您告诉Hangfire创建T的实例,然后访问T的方法,因此此签名仅适用于实例成员,而不是静态成员。如果使用其他“AddOrUpdate”方法签名之一而没有通用参数,则需要静态方法。
现在有趣的部分:如果类型T没有无参数的默认构造函数,则使用默认作业激活器会失败,就像您所说的那样。
这就是您现在可以使用自定义作业激活器为任务的构造函数提供依赖项的地方。如果创建从JobActivator继承的自己的类,则可以向您的作业提供依赖项。
以下是我的VB代码:
Imports Hangfire
Imports System.Reflection

Public Class JobActivationContainer
    Inherits JobActivator

    Private Property ParameterMap As Dictionary(Of Type, [Delegate])

    Private Function CompareParameterToMap(p As ParameterInfo) As Boolean
        Dim result = ParameterMap.ContainsKey(p.ParameterType)
        Return result
    End Function

    Public Overrides Function ActivateJob(jobType As Type) As Object
        Dim candidateCtor As Reflection.ConstructorInfo = Nothing
        'Loop through ctor's and find the most specific ctor where map has all types.
        jobType.
            GetConstructors.
            ToList.
            ForEach(
                Sub(i)
                    If i.GetParameters.ToList.
                        TrueForAll(AddressOf CompareParameterToMap) Then
                            If candidateCtor Is Nothing Then candidateCtor = i
                            If i IsNot candidateCtor AndAlso i.GetParameters.Count > candidateCtor.GetParameters.Count Then candidateCtor = i
                    End If
                End Sub
            )

            If candidateCtor Is Nothing Then
                'If the ctor is null, use default activator.
                Return MyBase.ActivateJob(jobType)
            Else
                'Create a list of the parameters in order and activate
                Dim ctorParameters As New List(Of Object)
                candidateCtor.GetParameters.ToList.ForEach(Sub(i)       ctorParameters.Add(ParameterMap(i.ParameterType).DynamicInvoke()))
            Return Activator.CreateInstance(jobType, ctorParameters.ToArray)
        End If
    End Function

    Public Sub RegisterDependency(Of T)(factory As Func(Of T))
        If Not ParameterMap.ContainsKey(GetType(T)) Then    ParameterMap.Add(GetType(T), factory)
    End Sub

    Public Sub New()
        ParameterMap = New Dictionary(Of Type, [Delegate])
    End Sub
End Class

我知道这并没有回答如何“滥用”静态变量的问题,但它展示了如何为Hangfire编写自己的IoC容器,或者按照手册使用已支持的IoC容器之一:http://hangfirechinese.readthedocs.org/en/latest/background-methods/using-ioc-containers.html 注意:我计划使用适当的IoC,上面的代码纯粹是学术性质的,需要大量工作!

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