我有一个有效的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
,但这并不能解决问题。
答案 0 :(得分:1)
这段代码可以重构了。
将调度程序放入IHostedService
中,并让其处理调度程序的启动。
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();
}
}
所以现在该服务将管理启动,并且所有必要的依赖项都将根据需要注入。
包括您的类型化客户Dependency
类
假设以下
public class Dependency : IDependency {
public Dependency(HttpClient httpClient) {
// <snipped>
}
}
public class Job1: IJob {
public Job1(IDependency dependency) {
// <snipped>
}
}
答案 1 :(得分:0)
事实证明,我同时遇到三个独立且无关的问题:
AddHttpClient<Dependency>()
注册了我的依存关系,我也不应包括AddSingleton<Dependency>()
。services.AddScoped<Job1>();
(谢谢@Nkosi)internal
构造函数。它必须是public
。 (可能是因为static async Task Main(string[] args)
是静态的,但我不确定。)