2013-07-19 157 views
4

我有一個MVC4 .Net Web應用程序在三層架構上的Unity依賴注入,並且我想每天收集一個verficiation併發送一些郵件。爲此,我想在Application_start中使用Quartz Scheduler,因爲依賴注入windows服務不是一個好選擇。Quartz.NET觸發器不會觸發,MVC4

這是我在application_start中的代碼。

 // construct a scheduler factory 
     ISchedulerFactory schedFact = new StdSchedulerFactory(); 
     IScheduler sched = schedFact.GetScheduler(); 
     sched.Start(); 

     IJobDetail dailyUserMailJob = new JobDetailImpl("DailyUserMailJob", null, typeof(SchedulerJob)); 
     // fire every time I open App/EveryDay 
     ITrigger dailyUserMailTrigger = new SimpleTriggerImpl("DailyUserMailTrigger", 1, 
               new TimeSpan(1, 0, 0, 0)); 
     sched.ScheduleJob(dailyUserMailJob, dailyUserMailTrigger); 

這裏是我的工作代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using EvaluationMvc.Bll.Contracts; 
using Quartz; 
using Quartz.Impl; 

namespace EvaluationMvc.Utils 
{ 
    public class SchedulerJob : IJob 
    { 
     private IEvaluationBus _iEvaluationBus; 

     public SchedulerJob(IEvaluationBus iEvaluationBus) 
     { 
     //Dependency injection 
      _iEvaluationBus = iEvaluationBus; 

     } 
     public void Execute(IJobExecutionContext context) 
     { 
     _iEvaluationBus.testingArchitecture(); 
     // Sends a test mail. 
     } 
    } 
}  

但是從不執行我的工作,可能是什麼問題呢?

回答

4

Quartz.net計劃程序必須創建爲singleton

您可以安裝Unity.MVC4 NuGet包。
這將創建一個引導程序類應該是這個樣子:

public static class Bootstrapper 
{ 
    public static IUnityContainer Initialise() 
    { 
     var container = BuildUnityContainer(); 
     DependencyResolver.SetResolver(new UnityDependencyResolver(container)); 
     return container; 
    } 

    private static IUnityContainer BuildUnityContainer() 
    { 
     var container = new UnityContainer(); 
     // Register your interfaces here. 
     RegisterTypes(container); 
     return container; 
    } 

    public static void RegisterTypes(IUnityContainer container) 
    { 
    } 
} 

然後,你必須創建自己的實現的的JobFactory。這article可以幫助你和this one是值得一讀:

public class UnityJobFactory: IJobFactory 
{ 
    private readonly IUnityContainer container; 

    static UnityJobFactory() 
    { 
    } 

    public UnityJobFactory(IUnityContainer container) 
    { 
     this.container = container; 
    } 

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) 
    { 
     var jobDetail = bundle.JobDetail; 
     var jobType = jobDetail.JobType; 

     try 
     { 
      return this.container.Resolve(jobType) as IJob; 
     } 
     catch (Exception ex) 
     { 
      throw new SchedulerException(string.Format(
       CultureInfo.InvariantCulture, 
       "Cannot instantiate class '{0}'", new object[] { jobDetail.JobType.FullName }), ex); 
     } 
    } 

    public void ReturnJob(IJob job) 
    { 
     // Nothing here. Unity does not maintain a handle to container created instances. 
    } 
} 

和自己實現StdSchedulerFactory

public class UnitySchedulerFactory : StdSchedulerFactory 
{ 
    private readonly UnityJobFactory unityJobFactory; 

    public UnitySchedulerFactory(UnityJobFactory unityJobFactory) 
    { 
     this.unityJobFactory = unityJobFactory; 
    } 

    protected override IScheduler Instantiate(QuartzSchedulerResources rsrcs, QuartzScheduler qs) 
    { 
     qs.JobFactory = this.unityJobFactory; 
     return base.Instantiate(rsrcs, qs); 
    } 
} 

再回到你的團結引導程序,你必須註冊你的接口:

private static IUnityContainer BuildUnityContainer() 
    { 
     var container = new UnityContainer(); 

     container.RegisterType<ISchedulerFactory, UnitySchedulerFactory>(new ContainerControlledLifetimeManager()); 
     container.RegisterType<IScheduler>(new InjectionFactory(c => c.Resolve<ISchedulerFactory>().GetScheduler())); 
     container.RegisterType<IQuartzScheduler, QuartzScheduler>(new ContainerControlledLifetimeManager()); 
     container.RegisterType<IEvaluationBus, EvaluationBus>(); 

     RegisterTypes(container); 

     return container; 
    } 

我已經包裝了d起來的一類我的服務調度,這樣我可以單創建它:

public interface IQuartzScheduler 
{ 
    void Run(); 
    void Stop(); 
} 

和:

public class QuartzScheduler : IQuartzScheduler 
{ 
    private readonly ISchedulerFactory SchedulerFactory; 
    private readonly IScheduler Scheduler; 

    public QuartzScheduler(ISchedulerFactory schedulerFactory, IScheduler scheduler) 
    { 
     this.SchedulerFactory = schedulerFactory; 
     this.Scheduler = scheduler; 
    } 

    public void Run() 
    { 
     IJobDetail dailyUserMailJob = new JobDetailImpl("DailyUserMailJob", null, typeof(Scheduler.SchedulerJob)); 
     // fire every time I open App/EveryDay 
     ITrigger dailyUserMailTrigger = new SimpleTriggerImpl("DailyUserMailTrigger", 10, 
               new TimeSpan(0, 0, 0, 20)); 

     this.Scheduler.ScheduleJob(dailyUserMailJob, dailyUserMailTrigger); 

     this.Scheduler.Start(); 
    } 

    public void Stop() 
    { 
     this.Scheduler.Shutdown(false); 
    } 
} 

正如你可以在這個類看,我會創造我的工作/觸發和啓動調度。

現在在您的Application_Start(global.asax)中,您可以「啓動」Unity容器,獲取服務調度程序並運行它。

var unityContainer = Infrastructure.Bootstrapper.Initialise(); 
unityContainer.Resolve<IQuartzScheduler>().Run(); 

您可以找到以下這linkQuartzWithUnity)工作示例。

+0

這幫了我很多。謝謝! –

0

非常有用,感謝LeftyX。我認爲,在Application_Start你必須創建這樣的服務:

var unityContainer = Bootstrapper.Initialise(); 
QuartzScheduler jobService = (QuartzScheduler)unityContainer.Resolve(typeof(QuartzScheduler), "Jobs"); 
jobService.Run();