具有依赖注入的Hangfire RecurringJob

Chr*_*sic 4 c# dependency-injection hangfire

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

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

public static void AddOrUpdate<T>(
    string recurringJobId,
    Expression<Action<T>> methodCall,
Run Code Online (Sandbox Code Playgroud)

关于我如何"滥用"静电来支持通道事物,我有几个想法,但我觉得我可能会遗漏一些东西.有没有一个设计决定,hangfire只支持chron工作中的静态?

J W*_*nia 14

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

RecurringJob.AddOrUpdate<EmailBackgroundTask>(x=>x.SendPeriodicEmail(),Cron.MinuteInterval(5));
Run Code Online (Sandbox Code Playgroud)

  • 当前(1.7.27)版本支持asp.net core依赖注入,无需添加JobActivator等,只需在启动时添加`AddHangfire()`即可。像上面的示例一样编写代码,Hangfire 将注入任何构造函数依赖项来创建“EmailBackgroundTask”。如果您使用不同的 DI 容器,您可能需要执行其他操作。 (2认同)

Ste*_*eve 1

快速回答是否定的,默认作业激活器仅适用于无参数构造函数或静态方法。我(在 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
Run Code Online (Sandbox Code Playgroud)

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

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