具有依赖项注入的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?
不确定它是什么时候添加的,但我只是在当前项目中做了类似的事情,它运行得很好。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,我上面的代码纯粹是学术性的,需要做很多工作!