2017-02-13 212 views
3

在我的项目中我必须使用Quartz,但我不知道我做错了什么。Quartz.Net依赖注入.Net Core

的JobFactory:

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(); 
     } 
    } 
} 

QuartzExtensions:

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); 
    } 
} 

,当我尝试运行我的工作(类具有依赖注入),我总是得到异常becouse:

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

是始终为空。

我的类实现IJob和startup.cs我补充一下:

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

app.UseQuartz(); 

我使用标准的.NET核心的依赖注入:

using Microsoft.Extensions.DependencyInjection; 
+0

你有没有在你的DI安装在您的工作吗? – Rabban

+0

我也只有一个工作,所以我安装了它'services.AddScoped ();' – donex93

回答

2

这我是如何在我的应用程序中完成的。而不是增加调度国际奥委会的我只加了工厂

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

我的工作的工厂几乎看起来是一样的。无论如何,暂时性并不重要,因为我只用过一次。我的石英扩展方法是

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类也是单例。

+0

'Quartz.Instance'在我的excample'scheduler'中?和'动作'这是什么?因为在我的应用程序中'Quartz'“Quartz是一个命名空间,但用于类型” – donex93

+0

'Quartz'是我自定义的类。这里是代码https://gist.github.com/Mats391/50cbf7f9c0291e623565dd0cc1baace3 – Mats391

+0

你是非常有帮助的。你可以告诉我在你的startup.cs你不使用'services.AddQuartz();'? 'UseQuartz'需要配置,所以你如何在Startup.cs中添加它? – donex93

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执行此操作。
我希望它可以帮助。

0

我得到了同样的问题。

我更新从

services.AddScoped<IJob, HelloJob>();

services.AddScoped<HelloJob>();

然后它工作。

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