C# ASP Core 2.1对Quartz的依赖项注入
我正在尝试将服务注入SendEmailJob类。 我使用标准ASP核心依赖项注入和Quartz库进行调度。 我正在尝试建立基于的解决方案。但我仍然面临注射问题 我有这样的代码设置:C# ASP Core 2.1对Quartz的依赖项注入,c#,asp.net-core,dependency-injection,quartz.net,C#,Asp.net Core,Dependency Injection,Quartz.net,我正在尝试将服务注入SendEmailJob类。 我使用标准ASP核心依赖项注入和Quartz库进行调度。 我正在尝试建立基于的解决方案。但我仍然面临注射问题 我有这样的代码设置: //Startup.cs, ConfigureServices ServiceAutoConfig.Configure(allServices); services.AddScoped<IUnitOfWork, UnitOfWork>(); services.AddTransient<IJobFa
//Startup.cs, ConfigureServices
ServiceAutoConfig.Configure(allServices);
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddTransient<IJobFactory, JobFactory>((provider) => new JobFactory(services.BuildServiceProvider()));
services.AddTransient<SendEmailJob>();
//Startup.cs, Configure
app.UseQuartz((quartz) => quartz.AddJob<SendEmailJob>("SendEmailJob", "Email", mailSettings.EmailSchedulerInterval));
JobFacctory的实施:
public class JobFactory : IJobFactory
{
protected readonly IServiceProvider _container;
public JobFactory(IServiceProvider container)
{
_container = container;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try
{
var res = _container.GetService(bundle.JobDetail.JobType) as IJob;
return res;
}
catch (Exception ex)
{
//ERROR- Cannot resolve 'Quartz.Jobs.SendEmailJob' from root provider because it
// requires scoped service 'BLL.Base.UnitOfWork.Interfaces.IUnitOfWork'.
throw;
}
}
public void ReturnJob(IJob job)
{
(job as IDisposable)?.Dispose();
}
}
Quartz.cs的实现
public class Quartz
{
private IScheduler _scheduler;
public static IScheduler Scheduler { get { return Instance._scheduler; } }
private static Quartz _instance = null;
public static Quartz Instance
{
get
{
if (_instance == null)
{
_instance = new Quartz();
}
return _instance;
}
}
private Quartz()
{
Init();
}
private async void Init()
{
_scheduler = await new StdSchedulerFactory().GetScheduler();
}
public IScheduler UseJobFactory(IJobFactory jobFactory)
{
Scheduler.JobFactory = jobFactory;
return Scheduler;
}
public async void AddJob<T>(string name, string group, int interval)
where T : IJob
{
IJobDetail job = JobBuilder.Create<T>()
.WithIdentity(name, group)
.Build();
ITrigger jobTrigger = TriggerBuilder.Create()
.WithIdentity(name + "Trigger", group)
.StartNow()
.WithSimpleSchedule(t => t.WithIntervalInSeconds(interval).RepeatForever()) // Mit wiederholung alle interval sekunden
.Build();
await Scheduler.ScheduleJob(job, jobTrigger);
}
public static async void Start()
{
await Scheduler.Start();
}
}
公共类石英
{
专用IScheduler\u调度器;
公共静态ISScheduler调度程序{get{return Instance.\u Scheduler;}}
私有静态石英_实例=null;
公共静态石英实例
{
得到
{
if(_instance==null)
{
_实例=新的Quartz();
}
返回_实例;
}
}
私人石英()
{
Init();
}
私有异步void Init()
{
_scheduler=等待新的StdSchedulerFactory().GetScheduler();
}
公共IScheduler UseJobFactory(IJobFactory jobFactory)
{
Scheduler.JobFactory=作业工厂;
返回调度程序;
}
公共异步void AddJob(字符串名称、字符串组、整数间隔)
T:IJob在哪里
{
IJobDetail job=JobBuilder.Create()
.WithIdentity(名称、组)
.Build();
ITrigger jobTrigger=TriggerBuilder.Create()
.WithIdentity(名称+触发器),组)
.StartNow()
.WithSimpleSchedule(t=>t.WithIntervalInSeconds(interval).RepeatForever())//Mit Wiederhoung alle interval sekunden
.Build();
wait Scheduler.ScheduleJob(作业,作业触发器);
}
公共静态异步void Start()
{
wait Scheduler.Start();
}
}
和UseQuartzExtension的实现:
public static void UseQuartz(this IApplicationBuilder app, Action<Quartz> configuration)
{
var jobFactory = new JobFactory(app.ApplicationServices);
Quartz.Instance.UseJobFactory(jobFactory);
configuration.Invoke(Quartz.Instance);
Quartz.Start();
}
publicstaticvoiduseQuartz(此IApplicationBuilder应用程序,动作配置)
{
var jobFactory=新的jobFactory(应用程序服务);
Quartz.Instance.UseJobFactory(jobFactory);
configuration.Invoke(Quartz.Instance);
Quartz.Start();
}
将IMessageService
注入SendMailJob
时出错。
因为它需要UnitOfWork
或在任何其他作用域服务上失败
你能给我解释一下如何正确注射吗 问题是您将
IUnitOfWork
注册为作用域,但在解决它时您没有任何作用域。在解决作业之前创建它:
public class JobFactory : IJobFactory, IDisposable
{
protected readonly IServiceScope _scope;
public JobFactory(IServiceProvider container)
{
_scope = container.CreateScope();
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var res = _scope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob;
return res;
}
public void ReturnJob(IJob job)
{
(job as IDisposable)?.Dispose();
}
public void Dispose()
{
_scope.Dispose();
}
}
我不确定您是否能够解决您在评论中提到的disposed DbContext问题,但我正在开发一个即将发布的.NET core应用程序,该应用程序具有相同的问题,并提出了一个类似于的解决方案,但在作业结束时使用并发字典来处理作用域。结果是在实例化新作业时,新的dbcontext被注入到我的作业中
public class QuartzJobFactory : IJobFactory
{
protected readonly IServiceProvider serviceProvider;
private ConcurrentDictionary<IJob, IServiceScope> scopes = new ConcurrentDictionary<IJob, IServiceScope>();
public QuartzJobFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
// instantiation of new job
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try {
var scope = serviceProvider.CreateScope();
var job = scope.ServiceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
scopes.TryAdd(job, scope);
return job;
}
catch (Exception ex) {
throw;
}
}
// executes when job is complete
public void ReturnJob(IJob job)
{
try {
(job as IDisposable)?.Dispose();
if (scopes.TryRemove(job, out IServiceScope scope))
scope.Dispose();
}
catch (Exception ex) {
}
}
}
公共类QuartzJobFactory:IJobFactory
{
受保护的只读IServiceProvider服务提供商;
私有ConcurrentDictionary作用域=新ConcurrentDictionary();
公共QuartzJobFactory(IServiceProvider服务提供商)
{
this.serviceProvider=serviceProvider;
}
//新作业的实例化
公共IJob NewJob(TriggerFiredBundle包,IScheduler调度器)
{
试一试{
var scope=serviceProvider.CreateScope();
var job=scope.ServiceProvider.GetRequiredService(bundle.JobDetail.JobType)作为IJob;
范围.TryAdd(作业,范围);
返回工作;
}
捕获(例外情况除外){
投掷;
}
}
//作业完成时执行
公共作业(IJob作业)
{
试一试{
(作业作为IDisposable)?.Dispose();
if(scopes.TryRemove(作业,超出IServiceScope范围))
scope.Dispose();
}
捕获(例外情况除外){
}
}
}
您不需要注册IMessageService吗?@MattjeS它已经配置好了。查看Startup.cs的更改。忘了在这里指定它它帮助修复了这个位置,但在Execute方法中它抛出了一个错误无法访问已处理的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,则可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入容器处理上下文实例。对象名称:“ApplicationDbContext”。
。有没有办法解决这个问题?
public class QuartzJobFactory : IJobFactory
{
protected readonly IServiceProvider serviceProvider;
private ConcurrentDictionary<IJob, IServiceScope> scopes = new ConcurrentDictionary<IJob, IServiceScope>();
public QuartzJobFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
// instantiation of new job
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
try {
var scope = serviceProvider.CreateScope();
var job = scope.ServiceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
scopes.TryAdd(job, scope);
return job;
}
catch (Exception ex) {
throw;
}
}
// executes when job is complete
public void ReturnJob(IJob job)
{
try {
(job as IDisposable)?.Dispose();
if (scopes.TryRemove(job, out IServiceScope scope))
scope.Dispose();
}
catch (Exception ex) {
}
}
}