【问题标题】:Quartz.Net Dependency Injection .Net CoreQuartz.Net 依赖注入 .Net Core
【发布时间】:2017-02-13 08:25:40
【问题描述】:

在我的项目中,我必须使用 Quartz,但我不知道我做错了什么。

工作工厂:

public class IoCJobFactory : IJobFactory
{
    private readonly IServiceProvider _factory;

    public IoCJobFactory(IServiceProvider factory)
    {
        _factory = factory;
    }
    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return _factory.GetService(bundle.JobDetail.JobType) as IJob;
    }

    public void ReturnJob(IJob job)
    {
        var disposable = job as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }
}

石英扩展:

public static class QuartzExtensions
{
    public static void UseQuartz(this IApplicationBuilder app)
    {
        app.ApplicationServices.GetService<IScheduler>();
    }

    public static async void AddQuartz(this IServiceCollection services)
    {
        var props = new NameValueCollection
        {
            {"quartz.serializer.type", "json"}
        };
        var factory = new StdSchedulerFactory(props);
        var scheduler = await factory.GetScheduler();

        var jobFactory = new IoCJobFactory(services.BuildServiceProvider());
        scheduler.JobFactory = jobFactory;
        await scheduler.Start();
        services.AddSingleton(scheduler);
    }
}

当我尝试运行我的作业(类有依赖注入)时,我总是得到异常,因为:

_factory.GetService(bundle.JobDetail.JobType) as IJob;

始终为空。

我的班级实现 IJob 并在 startup.cs 中添加:

services.AddScoped<IJob, HelloJob>();
services.AddQuartz();

app.UseQuartz();

我使用标准的 .net Core 依赖注入:

using Microsoft.Extensions.DependencyInjection;

【问题讨论】:

  • 您是否在 DI 中安装了作业?
  • 是的,我只有一份工作,所以我通过services.AddScoped&lt;IJob, HelloJob&gt;();安装了它

标签: c# .net asp.net-core scheduler quartz.net


【解决方案1】:

这只是我解决 IoC 问题的一个简单示例:

JobFactory.cs

public class JobFactory : IJobFactory
    {
        protected readonly IServiceProvider Container;

        public JobFactory(IServiceProvider container)
        {
            Container = container;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            return Container.GetService(bundle.JobDetail.JobType) as IJob;
        }

        public void ReturnJob(IJob job)
        {
            (job as IDisposable)?.Dispose();
        }
    }

Startup.cs

public void Configure(IApplicationBuilder app, 
            IHostingEnvironment env, 
            ILoggerFactory loggerFactory,
            IApplicationLifetime lifetime,
            IServiceProvider container)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseMvc();

            // the following 3 lines hook QuartzStartup into web host lifecycle
            var quartz = new QuartzStartup(container);
            lifetime.ApplicationStarted.Register(quartz.Start);
            lifetime.ApplicationStopping.Register(quartz.Stop);
        }

QuartzStartup.cs

public class QuartzStartup
    {
        private IScheduler _scheduler; // after Start, and until shutdown completes, references the scheduler object
        private readonly IServiceProvider container;

        public QuartzStartup(IServiceProvider container)
        {
            this.container = container;
        }

        // starts the scheduler, defines the jobs and the triggers
        public void Start()
        {
            if (_scheduler != null)
            {
                throw new InvalidOperationException("Already started.");
            }

            var schedulerFactory = new StdSchedulerFactory();
            _scheduler = schedulerFactory.GetScheduler().Result;
            _scheduler.JobFactory = new JobFactory(container);
            _scheduler.Start().Wait();

            var voteJob = JobBuilder.Create<VoteJob>()
                .Build();

            var voteJobTrigger = TriggerBuilder.Create()
                .StartNow()
                .WithSimpleSchedule(s => s
                    .WithIntervalInSeconds(60)
                    .RepeatForever())
                .Build();

            _scheduler.ScheduleJob(voteJob, voteJobTrigger).Wait();
        }

        // initiates shutdown of the scheduler, and waits until jobs exit gracefully (within allotted timeout)
        public void Stop()
        {
            if (_scheduler == null)
            {
                return;
            }

            // give running jobs 30 sec (for example) to stop gracefully
            if (_scheduler.Shutdown(waitForJobsToComplete: true).Wait(30000))
            {
                _scheduler = null;
            }
            else
            {
                // jobs didn't exit in timely fashion - log a warning...
            }
        }
    }  

考虑您应该提前将服务注册到容器(在我的情况下为 VoteJob)中。
我基于这个answer实现了这个。
我希望它会有所帮助。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。

    我更新自

    services.AddScoped&lt;IJob, HelloJob&gt;();

    services.AddScoped&lt;HelloJob&gt;();

    然后就可以了。

    _factory.GetService(bundle.JobDetail.JobType) as IJob; 不会为空:)

    【讨论】:

      【解决方案3】:

      这就是我在应用程序中的做法。我只添加工厂而不是将调度程序添加到 ioc 中

      services.AddTransient<IJobFactory, AspJobFactory>(
                      (provider) =>
                      {
                          return new AspJobFactory( provider );
                      } );
      

      我的工作工厂看起来几乎一样。瞬态并不重要,因为无论如何我只使用一次。那么我使用 Quartz 扩展的方法是

      public static void UseQuartz(this IApplicationBuilder app, Action<Quartz> configuration)
              {
                  // Job Factory through IOC container
                  var jobFactory = (IJobFactory)app.ApplicationServices.GetService( typeof( IJobFactory ) );
                  // Set job factory
                  Quartz.Instance.UseJobFactory( jobFactory );
      
                  // Run configuration
                  configuration.Invoke( Quartz.Instance );
                  // Run Quartz
                  Quartz.Start();
              }
      

      Quartz 类也是 Singleton。

      【讨论】:

      • Quartz.Instance 在我的例子中 schedulerAction&lt;Quartz&gt; 是什么?因为Quartz 在我的应用程序中“Quartz 是一个命名空间,但用作类型”
      • Quartz 是我制作的自定义类。这是代码gist.github.com/Mats391/50cbf7f9c0291e623565dd0cc1baace3
      • 你很有帮助。您能在您的 startup.cs 中告诉我您不使用 services.AddQuartz(); 吗?而UseQuartz 需要进行配置,那么如何在 Startup.cs 中添加它?
      • 这是来自我的 Startup.cs link 的 Quartz 相关资料
      • @donex93 我不明白。在Quartz 上,您可以随意添加和删除工作。出于我的目的,我从不需要删除工作,所以我没有为此烦恼。
      【解决方案4】:

      Quartz.NET 3.1 将包括对 Microsoft DI 和 ASP.NET Core 托管服务的官方支持。

      你可以找到重新访问的包:

      查看正在进行的新 DI 集成的最佳资源是前往the example ASP.NET Core application

      https://www.quartz-scheduler.net/2020/07/08/quartznet-3-1-beta-1-released/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-22
        • 1970-01-01
        • 2021-10-23
        • 2021-02-02
        • 1970-01-01
        • 2020-12-20
        • 2018-03-03
        • 2021-07-15
        相关资源
        最近更新 更多