c# - 添加使用多个服务的重复作业
问题描述
因此,Hangfire 提供了IRecurringJobManager
我们可以用来添加重复作业的功能,但它只支持注入一项服务,当我需要访问多项服务时,我找不到任何示例说明如何执行此操作。
考虑我有两个这样的注册服务:
services.AddTransient<Service1>();
services.AddTransient<Service2>();
我想在我的经常性工作中使用它们。理想情况下,我想做的是:
recurringJobManager.AddOrUpdate<Service1, Service2>("my-job", (service1, service2) =>
{
// do something
}, Cron.Daily);
但这是不可能的。
这样做的正确方法是什么?我应该注入 IServiceProvider 吗?像这样?
recurringJobManager.AddOrUpdate<IServiceProvider>("my-job", (serviceProvider) =>
{
var service1 = serviceProvider.GetRequiredService<Service1>();
var service2 = serviceProvider.GetRequiredService<Service2>();
// do something
}, Cron.Daily);
那会奏效吗?编辑:不,因为我不能在里面使用语句体
我有点困惑,因为文档没有涵盖这些情况。
解决方案
一种解决方案似乎是用我需要的服务创建一个单独的类
public class MyJob
{
private readonly Service1 _service1;
private readonly Service2 _service2;
public MyJob(Service1 service1, Service2 service2)
{
_service1 = service1;
_service2 = service2;
}
public void DoSomething() {}
}
然后像这样使用它:
recurringJobManager.AddOrUpdate<MyJob>("my-job", myJob => myJob.DoSomething(), Cron.Daily);
注意:我们不能将语句体{}
与AddOrUpdate
. 它始终需要是单个方法调用,因为它需要Expression<T>
作为参数。因此,如果我们尝试这样做,recurringJobManager.AddOrUpdate<MyJob>("my-job", myJob => {myJob.DoSomething(); myJob.DoSomething2();}, Cron.Daily);
我们将得到编译器错误。
另一种解决方案是将 IServiceProvider 作为参数的单独方法。但我不能保证它有效。
// Or just use MyJob without any parameters if it has access to Service1 and Service2 in case they're members of your class.
private void MyJob(IServiceProvider services)
{
var service1 = services.GetRequiredService<Service1>();
var service2 = services.GetRequiredService<Service2>();
// do something
}
// Add like this or just inject `IServiceProvider` somewhere else e.g. in Configure method
recurringJobManager.AddOrUpdate<IServiceProvider>("my-job", services => MyJob(services), Cron.Daily);
还要检查https://docs.hangfire.io/en/latest/best-practices.html#best-practices
因此,理想情况下,您不应将IServiceProvider
其用作工作参数,因为它将被序列化。
⚠️ 重要的事情一开始让我非常困惑!
当你这样做时
var myJob = new MyJob();
RecurringJob.AddOrUpdate("my-job", () => myJob.Run(), Cron.Hourly(0));
它不会使用您创建的那个实例,而是每次都创建一个新实例。所以上面的代码100%等效于
RecurringJob.AddOrUpdate<MyJob>("my-job", (myJob) => myJob.Run(), Cron.Hourly(0));
因为 AddOrUpdate 在内部所做的是解析表达式,确定 myJob 的类型和调用的方法,并构造一个新表达式来创建该类型的实例并在新实例上调用该方法。
推荐阅读
- reactjs - 在反应js中将数据附加为表格
- jquery - table2excel:Excel 文件已下载但未在 msoffice 中打开
- python - 如何在 Jinja 2 模板中传递转义字符串变量
- r - 获取R中的组序列
- python - 熊猫中列名的单元格值
- php - 在 PHP 类中分配会话变量
- c - 无法从c中的循环链表中删除第一个元素
- reactjs - 反应原生。VirtualizedList:PureComponent、shouldComponentUpdate等
- php - 如何将 Preg_match 用于数组(多键)?
- r - R:如何通过修改以前的ID来改变新的ID?