Hangfire RecurringJob with dependency injection

时间:2015-10-30 21:38:00

标签: c# dependency-injection hangfire

Is it possible to have Hangfire instantiate objects with the configure JobActivator when they're scheduled to run as a RecurringJob?

The signature of the method seems to force static only usages:

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

I have several ideas on how i could "abuse" statics to back channel things around, but i feel like i might be missing something. Was there a design decision that hangfire only supports statics in chron jobs?

2 个答案:

答案 0 :(得分:12)

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

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

答案 1 :(得分:0)

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

通过使用&#34; AddOrUpdate&#34;,您告诉Hangfire创建T的实例,然后访问T的方法,因此此签名适用于实例成员,而不是静态。如果您使用其中一个&#34; AddOrUpdate&#34;如果方法签名没有泛型参数,则需要静态。

现在有趣的部分:如果类型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

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

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