c# - 具有多级 DI 的 Quartz.Net 作业
问题描述
我有一个JobFactory : IJobFactory
有效的。我可以很好地创建预定的作业,并毫无问题地注入简单的依赖项,但我确实遇到了一个问题。依赖项之一本身取决于HttpClient
,但这似乎不起作用。
例如
services.AddHttpClient<Dependency>("dependency");
services.AddSingleton(typeof(Dependency));
using (var serviceProvider = services.BuildServiceProvider())
{
var schedulerFactory = new StdSchedulerFactory();
var scheduler = await schedulerFactory.GetScheduler();
scheduler.JobFactory = new JobFactory(serviceProvider);
await scheduler.Start();
var job = JobBuilder.Create<Job1>()
.WithIdentity("job1")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("trigger1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInSeconds(1)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(job, trigger);
}
依赖构造函数是
public Dependency(HttpClient httpClient)
{
// <snipped>
}
和工作构造函数是
public Job1(Dependency dependency)
{
// <snipped>
}
当我尝试运行它时,我被告知该作业正在引发未处理的异常。通过我的 JobFactory 进行调试告诉我 httpClient 根本没有被注入。.AddHttpClient 不应该处理这个吗?是否因为 DI 的多个级别而不起作用?是否可以采取另一种方式?
请注意,我也尝试Job1
像我一样手动注册Dependency
,但这并没有解决问题。
解决方案
这段代码重构的时机已经成熟。
将调度程序放入 aIHostedService
并让它处理调度程序的启动。
public interface IHostedService {
//
// Summary:
// Triggered when the application host is ready to start the service.
Task StartAsync(CancellationToken cancellationToken);
//
// Summary:
// Triggered when the application host is performing a graceful shutdown.
Task StopAsync(CancellationToken cancellationToken);
}
public class SchedulerService : IHostedService {
readonly IJobFactory jobFactory;
readonly ISchedulerFactory schedulerFactory
IScheduler scheduler;
public SchedulerService(IJobFactory jobFactory, ISchedulerFactory schedulerFactory) {
this.jobFactory = jobFactory;
this.schedulerFactory = schedulerFactory;
}
public async Task StartAsync(CancellationToken cancellationToken) {
scheduler = await schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
IJobDetail job = JobBuilder.Create<Job1>()
.WithIdentity("job1")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(1)
.RepeatForever())
.Build();
await scheduler.ScheduleJob(job, trigger);
await scheduler.Start(cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken) {
return scheduler.Shutdown(cancellationToken);
}
}
有了这些,现在可以通过将所有类型添加到服务集合来在启动时干净地完成配置
class Program {
static async Task Main(string[] args) {
var services = new ServiceCollection();
//...
services.AddHttpClient<IDependency, Dependency>();
services.AddScoped<Job1>();
services.AddTransient<ISchedulerFactory, StdSchedulerFactory>();
services.AddTransient<IJobFactory>(serviceProvider => new JobFactory(serviceProvider));
services.AddTransient<IHostedService, SchedulerService>();
//...
IServiceProvider serviceProvider = services.BuildServiceProvider();
var service = serviceProvider.GetRequiredService<IHostedService>();
await service.StartAsync();
Console.ReadKey();
}
}
因此,现在该服务将管理启动,并且所有必要的依赖项都将根据需要注入。
包括您的 Typed ClientDependency
类,假设如下
public class Dependency : IDependency {
public Dependency(HttpClient httpClient) {
// <snipped>
}
}
public class Job1: IJob {
public Job1(IDependency dependency) {
// <snipped>
}
}
推荐阅读
- typescript - 类实例在 TypeScript 中返回空白对象
- firebase - 即使用户在 facebook 登录过程中拒绝它,我也有兴趣获取用户的电子邮件地址
- javascript - 将数组中的元素从某个索引移动到 0
- javascript - 图像过滤器插件在一个项目中有效,但在另一个项目中无效
- flutter - 用于下载种子的 Flutter 插件
- python - 包含多个元素的 Zip 列表
- sql - 使用来自 3 个表的 INNER JOIN 进行 UPDATE 操作
- c# - 我想使用 ac# windows form 应用程序将我的数据库备份到我想要的位置
- angular - 如何在 Angular 中使用 observable 初始化 Typescript 数组接口
- c++ - 锁在并行编程中是如何工作的?