Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP Core 2.1对Quartz的依赖项注入_C#_Asp.net Core_Dependency Injection_Quartz.net - Fatal编程技术网

C# ASP Core 2.1对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

我正在尝试将服务注入SendEmailJob类。 我使用标准ASP核心依赖项注入和Quartz库进行调度。 我正在尝试建立基于的解决方案。但我仍然面临注射问题

我有这样的代码设置:

//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) {

        }
    }
}