2013-07-19 3 views
4

У меня есть веб-приложение MVC4 .Net на трехуровневой архитектуре с инъекцией зависимости Unity, и я хочу ежедневно рассылать информацию о проверке и отправлять по почте некоторые письма. Для этого я хочу использовать Quartz Scheduler в Application_start, потому что служба 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 Package.
Это создаст Bootstrapper класс, который должен выглядеть примерно так:

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

Возвращаясь к вашему Unity Bootstrapperвы должны зарегистрировать свои интерфейсы:

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

Вы можете найти рабочий образец после этой link (QuartzWithUnity).

+0

Это очень помогло мне. Благодаря! –

0

Очень полезно, спасибо LeftyX. Я думаю, в Application_Start вам необходимо создать такой сервис:

var unityContainer = Bootstrapper.Initialise(); 
QuartzScheduler jobService = (QuartzScheduler)unityContainer.Resolve(typeof(QuartzScheduler), "Jobs"); 
jobService.Run(); 
Смежные вопросы