具有依赖项注入的Hangfire RecurringJob

本文关键字:Hangfire RecurringJob 注入 依赖 | 更新日期: 2023-09-27 18:20:09

当Hangfire对象计划作为RecurringJob运行时,是否可以使用configure JobActivator实例化对象?

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

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

我有几个关于如何"滥用"静态信息来反向传播的想法,但我觉得我可能错过了什么。是否有一个设计决策认为hangfire只支持chron作业中的statics?

具有依赖项注入的Hangfire RecurringJob

不确定它是什么时候添加的,但我只是在当前项目中做了类似的事情,它运行得很好。EmailBackgroundTask是一个非静态类,也是一个非静止方法。该类通过Hangfire.Unity DI包注入了4个依赖项。

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

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

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

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

这就是您现在可以使用自定义jobactivator为任务的构造函数提供依赖关系的地方。如果您从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

我知道这并不能回答如何"滥用"静态的问题,但它确实表明了你可以如何滚动你自己的IoC容器进行上火,或者根据手册使用一个已经支持的IoC:http://hangfirechinese.readthedocs.org/en/latest/background-methods/using-ioc-containers.html

注意:我计划使用一个合适的IoC,我上面的代码纯粹是学术性的,需要做很多工作!