【问题标题】:Hangfire RecurringJob with dependency injectionHangfire RecurringJob 与依赖注入
【发布时间】:2015-10-30 21:38:00
【问题描述】:

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

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

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

关于如何“滥用”静态数据来反向引导事物,我有几个想法,但我觉得我可能遗漏了一些东西。是否有设计决定 hangfire 仅支持 chron 作业中的静态?

【问题讨论】:

    标签: c# dependency-injection hangfire


    【解决方案1】:

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

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

    【讨论】:

    • 我不确定在问这个问题时接受的答案是否是这种情况,但这应该是现在接受的答案。
    • 这不使用依赖注入系统,它只是提供了作为泛型参数提到的类型的默认实例。就像文档 (docs.hangfire.io/en/latest/background-methods/…) 中提到的那样,实现像 @Steve 这样的 JobActivator 是实际的解决方案
    • 当前(1.7.27)版本支持asp.net核心依赖注入,无需添加JobActivator等,只需在启动时添加AddHangfire()即可。像上面的示例那样编写代码,Hangfire 将注入任何构造函数依赖项来创建EmailBackgroundTask。如果您使用不同的 DI 容器,您可能需要执行其他操作。
    【解决方案2】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-14
      • 2017-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多