介绍
我知道关于这个主题有很多文章和某种教程,我什至没有在谈论官方文档,但是在进行我的最新项目时,遇到了一个非常有趣的问题,没有太多提及。今天,我们将讨论在ASP.NET Core项目中使用依赖注入和Quartz的问题。一切始于我不认为会出现任何问题的事实,我会立即说我尝试使用各种方法:我添加了Quartz包含在服务中的所有类,并通过DI使用它们-by(但不完全是, (后来发现),我尝试添加HostedService-也不起作用(最后,我将在有关使用Quartz的有用文章上附加一些很好的链接)等等。我已经以为触发器有问题-两者都没有。在这篇简短的文章中,我将尝试帮助那些可能遇到相同问题的人,并希望我的解决方案对他们将来的工作有所帮助。在引言的结尾,我想补充一点,如果我在评论中对本技术非常了解的人给出一些建议,这些建议可以帮助改善我的建议,我将非常感激。石英
创建一个项目(或完成一个项目-没关系),并向其中添加两个文件夹和几个类:Quartz--DataJob.cs--DataScheduler.cs--JobFactory.csWorkers--EmailSender--IEmailSender在IEmailSender界面中,将作为示例,创建一种向信件发送信件的方法:public interface IEmailSender
{
Task SendEmailAsync(string email, string subject, string message);
}
现在,我们描述将实现此接口的类:public class EmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string message)
{
var from = "****@gmail.com";
var pass = "****";
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential(from, pass);
client.EnableSsl = true;
var mail = new MailMessage(from, email);
mail.Subject = subject;
mail.Body = message;
mail.IsBodyHtml = true;
return client.SendMailAsync(mail);
}
}
现在,我们描述类DataJob.cs,DataScheduler.cs,JobFactory.cs。DataJob类将实现IJob接口。 public class DataJob : IJob
{
private readonly IServiceScopeFactory serviceScopeFactory;
public DataJob(IServiceScopeFactory serviceScopeFactory)
{
this.serviceScopeFactory = serviceScopeFactory;
}
public async Task Execute(IJobExecutionContext context)
{
using (var scope = serviceScopeFactory.CreateScope())
{
var emailsender = scope.ServiceProvider.GetService<IEmailSender>();
await emailsender.SendEmailAsync("example@gmail.com","example","hello")
}
}
}
正如我们看到的IServiceScopeFactory类型的字段一样,我们将直接从Startup获取服务。正是这种方法帮助我解决了问题,继续描述了DataScheduler类,我们将在其中添加作业并在石英本身的Sheduler中进行触发:public static class DataScheduler
{
public static async void Start(IServiceProvider serviceProvider)
{
IScheduler scheduler = await StdSchedulerFactory.GetDefaultScheduler();
scheduler.JobFactory = serviceProvider.GetService<JobFactory>();
await scheduler.Start();
IJobDetail jobDetail = JobBuilder.Create<DataJob>().Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("MailingTrigger", "default")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(1)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(jobDetail, trigger);
}
现在是JobFactory类,它实现了IJobFactory接口: public class JobFactory : IJobFactory
{
protected readonly IServiceScopeFactory serviceScopeFactory;
public JobFactory(IServiceScopeFactory serviceScopeFactory)
{
this.serviceScopeFactory = serviceScopeFactory;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
using (var scope = serviceScopeFactory.CreateScope())
{
var job = scope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob;
return job;
}
}
public void ReturnJob(IJob job)
{
}
}
如您所见,实际上,我直接从serviceScopeFactory获取所有依赖项。一切准备就绪,仍然需要更改Program类:public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var serviceProvider = scope.ServiceProvider;
try
{
DataScheduler.Start(serviceProvider);
}
catch (Exception)
{
throw;
}
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
并将以下内容添加到“启动”中的ConfigureServices方法: services.AddTransient<JobFactory>();
services.AddScoped<DataJob>();
services.AddScoped<IEmailSender,EmailSender>();
做完了 现在,当您启动应用程序时,我们创建一个将在每分钟触发的任务。可以在DataScheduler.Start中更改该值(也可以以秒,小时为单位或使用CRON进行指定)。对于使用这种方法的每个新任务,您需要创建一个新类,该类将实现IJob并注册一个新的DataScheduler任务。您也可以为新任务创建单独的Scheduler类。如果可以帮助某人,我将非常高兴,但是这里有几篇有关Quartz及其用法的有用文章:使用ASP.NET Core创建Quartz.NET托管服务在ASP.NET Core中使用Quartz.NET托管服务中的作用域服务