我正在用FluentScheduler来实验ASP.net核心API中的一些后台任务。
作业应该根据很少的标准每天在特定的时间间隔发送推送通知。我已经浏览了文档并实现了一个测试功能,用于在控制台窗口中打印一些输出。它在预期的时间间隔内起作用。
但我要做的实际工作涉及数据库上下文,它提供了执行发送通知的标准所必需的信息。
我的问题是我无法在MyJob类中使用带有参数的构造函数,这将引发丢失的方法异常。
PS:,根据Scott的这篇文章,FluentScheduler似乎相当有名,但我无法从在线社区获得任何帮助。但很明显,这很容易理解。
public class MyJob : IJob
{
private ApplicationDbContext _context;
public MyJob(ApplicationDbContext context)
{
_context = context;
}
public void Execute()
{
Console.WriteLine("Executed");
SendNotificationAsync();
}
private async Task SendNotificationAsync()
{
var overdues = _context.Borrow.Join(
_context.ApplicationUser,
b => b.ApplicationUserId,
a => a.Id,
(a, b) => new { a, b })
.Where(z => (z.a.ReturnedDate == null) && (z.a.BorrowApproval == 1))
.Where(z => z.a.ReturnDate.Date == new DateTime().Date.AddDays(1).Date)
.Select(z => new { z.a.ApplicationUserId, z.a.Book.ShortTitle, z.a.BorrowedDate, z.b.Token })
.ToList();
Console.WriteLine("Acknowledged");
foreach (var r in overdues)
{
string message = "You are running late! The book '" + r.ShortTitle + "' borrowed on '" + r.BorrowedDate + "' due tomorrow.";
Console.WriteLine(message);
await new PushNotificationService().sendAsync(r.Token, "Due Tomorrow!", message);
}
}
}发布于 2017-08-09 15:16:14
从源代码 for IJob看来,实现IJob的类需要有一个无参数的默认构造函数。由于FluentScheduler也是支撑羔羊,所以让依赖项注入库创建对象可能更容易,然后按如下方式调用Execute方法:
var myJob = new MyJob(new ApplicationDbContext());
Schedule(() => myJob.Execute()).ToRunEvery(1).Days().At(21, 15);或者自己调用构造函数:
// Schedule a job using a factory method and pass parameters to the constructor.
Schedule(() => new MyJob(new ApplicationDbContext())).ToRunNow().AndEvery(2).Seconds();发布于 2018-03-29 11:35:22
Note -在文档中,它说不要使用IJobFactory,因为它很快就会被废弃,但是在过去的3,4个月里,它在生产中为我工作-- https://github.com/fluentscheduler/FluentScheduler/issues/71
我在Windows应用程序中使用Autofac和Fluent Scheduler,它使用TopShelf作为Windows运行它。
要在FluentScheduler中使用依赖项注入,您必须设置一个作业工厂来解决依赖关系。
因此,首先通过实现JobFactory来设置IJobFactory
就像这样-
public class MyJobFactory : IJobFactory
{
public IJob GetJobInstance<T>() where T : IJob
{
return MyContainer.GetJobInstance<T>();
}
}现在在Job中,因为我使用的是Autofac,所以我正在设置一个容器,它有两个方法
1- ConfigureDependencies() -它只被调用一次以设置容器:
2- GetJobInstance() - MyJobFactory调用它来解析作业实例
public class MyContainer
{
public static IContainer Container { get; set; }
public static void ConfigureDependencies()
{
var builder = new ContainerBuilder();
// Jobs
builder.RegisterType<MyJob>().As<MyJob>();
// DB Contexts
// Others
Container = builder.Build();
}
public static IJob GetJobInstance<T>() where T : IJob
{
return Container.Resolve<T>();
}
}然后,当您启动应用程序/服务时,它将如下所示。
public void Start()
{
// Configure Dependency Injection
MyContainer.ConfigureDependencies();
// Setup the Fluent Scheduler -
JobManager.JobFactory = new MyJobFactory();
JobManager.UseUtcTime();
JobManager.Initialize(new MyJobRegistry());
}然后我通过添加两个构造函数创建了一个作业-
1-参数减
2-具有注入对象的构造函数
例如:
public class MyJob : IJob
{
public static string JobName = "MyJob";
private readonly ICompaniesProvider _companiesProvider;
// parameter-less constructor
public MyJob() { }
// injecting HERE
public MyJob(ICompaniesProvider companiesProvider)
{
_companiesProvider = companiesProvider;
}
public void Execute()
{
}
}编辑
由于IJobFactory这个不受欢迎的问题,您可以直接调用容器并在将它添加到JobManager之前获取一个作业实例
public void Start()
{
// Configure Dependency Injection
MyContainer.ConfigureDependencies();
JobManager.UseUtcTime();
JobManager.Start();
var myJob = MyContainer.GetJobInstance<MyJob>();
Action<Schedule> schedule = s => s.ToRunEvery(1).Hours().At(0);
JobManager.AddJob(myJob, schedule);
}发布于 2018-07-04 07:21:38
我在这里发布了类似的答案- https://stackoverflow.com/a/51167073/7166609
我使用了Application服务作用域,将其注入到注册表的构造函数中,并使用该作用域获取作业类的execute方法中的对象。
https://stackoverflow.com/questions/45593321
复制相似问题