具有依赖注入的 Hangfire RecurringJob

Hangfire RecurringJob with dependency injection

当对象被安排为 运行 作为 RecurringJob 时,是否可以让 Hangfire 使用配置 JobActivator 实例化对象?

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

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

我有几个关于如何 "abuse" 静力学来反向引导周围事物的想法,但我觉得我可能遗漏了一些东西。是否有 hangfire 仅支持 chron 作业中的静态的设计决策?

快速回答是否定的,默认作业激活器仅适用于无参数构造函数或静态方法。我做了一些事情(在 VB.net 中)快速而肮脏地看看我是否可以让它工作并在下面显示它。

通过使用 "AddOrUpdate",你告诉 Hangfire 创建一个 T 的实例,然后访问 T 的方法,所以这个签名适用于实例成员,而不是静态。如果您使用不带通用参数的其他 "AddOrUpdate" 方法签名之一,它将需要一个静态的。

现在是有趣的部分:如果类型 T 没有无参数的默认构造函数,那么它会像您所说的那样使用默认的 jobactivator 失败。

现在您可以在此处使用自定义 jobactivator 为任务的构造函数提供依赖项。如果您创建自己的 class 从 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

我知道这并没有回答关于如何 "abuse" 静态的问题,但它确实展示了如何为 hangfire 滚动你自己的 IoC 容器,或者使用一个已经支持的 IoC 作为根据手册:http://hangfirechinese.readthedocs.org/en/latest/background-methods/using-ioc-containers.html

注意:我打算使用适当的 IoC,我上面的代码纯粹是学术性的,需要大量工作!

不确定它是什么时候添加的,但我只是在我当前的项目中做了类似的事情并且它工作正常。 EmailBackgroundTask 是一个非静态的 class,这是一个非静态的方法。 class 有 4 个依赖项通过 Hangfire.Unity DI 包注入。

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