2013-06-04 12 views
15

Ich versuche, Quartz.net (2.1.2) mit einem IoC-Container (Autofac) zu arbeiten, da ich Dienste habe, die ich im geplanten verwenden muss Arbeitsplätze. Ich habe ähnliche Beiträge zu diesem Thema gefunden, aber ich kann keine mit einem spezifischen Registrierungsbeispiel für Autofac finden.Wie erstelle ich einen Job von Quartz.NET, der eine Injektion mit Autofac benötigt

Die folgende Beitrag befasst sich mit dem gleichen Problem das ich habe:

How to schedule task using Quartz.net 2.0?

der Teil I ich bin fehlt, ist jedoch der Meinung, wenn die Antwort sagt: „Und vergessen Sie nicht, den Job in registrieren der IoC-Container ". Ich bin mir nicht sicher, wie ich das genau machen soll, da alles, was ich bisher versucht habe, nicht funktioniert hat.

Im folgenden Beispiel wird "HelloJob" ausgeführt, aber wenn ich versuche, den releaseService in den "ReleaseJob" zu injizieren, weigert er sich zu laufen.

Update: I markiert den Code in der DependencyRegistration.cs wo ich glaube, das Problem ist.

Update 2: einige relevante Links, die auf verwandt sind, was ich tun müssen, und könnte helfen (Ich habe bereits durch sie gegangen alle, aber immer noch nicht herausfinden können, wie dies mit Autofac zum Laufen zu bringen):

Wie verwendet man Quartz.NET in PRO-Weise? - http://blog.goyello.com/2009/09/21/how-to-use-quartz-net-in-pro-way/

Autofac und Quartz.NET - http://blog.humann.info/post/2013/01/30/Autofac-and-QuartzNET.aspx

Constructor Injektion mit Quartz.NET und einfachen Injector - Constructor injection with Quartz.NET and Simple Injector

ASP.Net MVC 3, Ninject und Quarz .Net - Wie? - ASP.Net MVC 3, Ninject and Quartz.Net - How to?

Hier ist der relevante Code:

Global.asax

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 

     var dependencyRegistration = new DependencyRegistration(); 
     dependencyRegistration.Register(); 

     ModelValidatorProviders.Providers.Clear(); 
     ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(new ValidatorFactory())); 

     DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false; 
    } 

DependencyRegistration.cs

public class DependencyRegistration 
{ 
    public void Register() 
    { 
     var builder = new ContainerBuilder(); 

     builder.RegisterControllers(Assembly.GetExecutingAssembly()); 
     builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly()); 

     // Validation 
     builder.RegisterType<ValidatorFactory>() 
      .As<IValidatorFactory>() 
      .InstancePerHttpRequest(); 

     AssemblyScanner findValidatorsInAssembly = AssemblyScanner.FindValidatorsInAssembly(Assembly.GetExecutingAssembly()); 
     foreach (AssemblyScanner.AssemblyScanResult item in findValidatorsInAssembly) 
     { 
      builder.RegisterType(item.ValidatorType) 
       .As(item.InterfaceType) 
       .InstancePerHttpRequest(); 
     } 

     // Schedule 
     builder.Register(x => new StdSchedulerFactory().GetScheduler()).As<IScheduler>(); 

     // Schedule jobs 
     builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).Where(x => typeof(IJob).IsAssignableFrom(x)); 

     var container = builder.Build(); 
     DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

     //Schedule 
     IScheduler sched = container.Resolve<IScheduler>(); 
     sched.JobFactory = new AutofacJobFactory(container); 
     sched.Start(); 

     IJobDetail job = JobBuilder.Create<ReleaseJob>() 
       .WithIdentity("1Job") 
       .Build(); 

     ITrigger trigger = TriggerBuilder.Create() 
      .WithIdentity("1JobTrigger") 
      .WithSimpleSchedule(x => x 
       .RepeatForever() 
       .WithIntervalInSeconds(5) 
      ) 
      .StartNow() 
      .Build(); 

     sched.ScheduleJob(job, trigger); 

     job = JobBuilder.Create<HelloJob>() 
       .WithIdentity("2Job") 
       .Build(); 

     trigger = TriggerBuilder.Create() 
      .WithIdentity("2JobTrigger") 
      .WithSimpleSchedule(x => x 
       .RepeatForever() 
       .WithIntervalInSeconds(5) 
      ) 
      .StartNow() 
      .Build(); 

     sched.ScheduleJob(job, trigger); 
    } 
} 

JobFactory.cs

public class AutofacJobFactory : IJobFactory 
{ 
    private readonly IContainer _container; 

    public AutofacJobFactory(IContainer container) 
    { 
     _container = container; 
    } 

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) 
    { 
     return (IJob)_container.Resolve(bundle.JobDetail.JobType); 
    } 

    public void ReturnJob(IJob job) 
    { 
    } 
} 

ReleaseJob.cs

public class ReleaseJob : IJob 
{ 
    private readonly IReleaseService _releaseService; 

    public ReleaseJob(IReleaseService releaseService) 
    { 
     this._releaseService = releaseService; 
    } 

    public void Execute(IJobExecutionContext context) 
    { 
     Debug.WriteLine("Release running at " + DateTime.Now.ToString()); 
    } 
} 

public class HelloJob : IJob 
{ 
    public void Execute(IJobExecutionContext context) 
    { 
     Debug.WriteLine("Hello job at " + DateTime.Now.ToString()); 
    } 
} 

ReleaseServiceModel.cs

public class ReleaseServiceModule : Module 
{ 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<ReleaseService>() 
      .As<IReleaseService>() 
      .InstancePerLifetimeScope(); 
    } 
} 
+0

Sie haben mir die Zeit gerettet, dies herauszufinden. Vielen Dank Tomas. – slashp

Antwort

5

Ich endlich herausgefunden, was das Problem war.

Mein Veröffentlichungsdienst verwendete ein Datenrepository, das mit einem anderen Bereich erstellt wurde.

Ich entdeckte dies, indem ich einen neuen Testdienst erstellte, der nur eine Zeichenfolge zurückgab, und das funktionierte in einen Quarzjob.

Als ich dies entdeckte, änderte ich den Umfang des Repository, das vom Release-Service aufgerufen wurde, und dann begann der Release-Service innerhalb des Quarz-Jobs zu arbeiten.

Ich entschuldige mich bei allen, die diese Frage anschauten, um mir zu helfen. Da der Code des Freigabedienstes nicht aufgeführt war, wäre es schwierig gewesen, herauszufinden, was falsch war.

Ich habe den Code mit den letzten Arbeitsbindungen aktualisiert, die ich für Quarz mit Autofac verwendet habe.

+0

Hallo Thomas - Es tut uns leid, einen alten Post zurück zu bringen, aber haben Sie ein Beispiel dafür, wie Sie den Umfang Ihres Dienstes geändert haben, um dies zu berücksichtigen. Ich falle in die selbe Falle, wo ich nicht zu sehr in der Abhängigkeitsinjektion erfahren habe und dies nicht zur Arbeit bringen kann:/ – SM3RKY

+0

Ich glaube, dass es den Bereich von "InstancePerHttpRequest" geändert hat, der nicht funktionierte, bis "InstancePerLifetimeScope", das funktioniert Repository- und Releaseservice-Module. – Tomas

0

Das Problem ist, dass Ihr AutofacJobFactory nicht schafft die ReleaseJob (Sie tun dies mit JobBuilder.Create<ReleaseJob>() statt), so dass der IoC-Container ist nicht bekannt, es bedeutet Instanziierung Dependency Injection nicht auftreten kann.

sollte der folgende Code arbeiten:

sched = schedFact.GetScheduler(); 
sched.JobFactory = new AutofacJobFactory(container); 
sched.Start(); 

// construct job info 
JobDetailImpl jobDetail = new JobDetailImpl("1Job", null, typeof(ReleaseJob)); 

ITrigger trigger = TriggerBuilder.Create() 
    .WithIdentity("1JobTrigger") 
    .WithSimpleSchedule(x => x 
     .RepeatForever() 
     .WithIntervalInSeconds(5) 
    ) 
    .StartNow() 
    .Build(); 

sched.ScheduleJob(jobDetail, trigger); 

Beachten Sie, dass wir in diesem Beispiel nicht mehr JobBuilder.Create<ReleaseJob>() verwenden, stattdessen geben wir die Einzelheiten des Auftrags über das JobDetailImpl Objekt erstellt werden und von dieser ist der Planer tun jobfactory (AutofacJobFactory) ist verantwortlich für die Instanziierung des Jobs und die Abhängigkeitsinjektion kann auftreten.

+0

Ich habe die von Ihnen empfohlene Änderung vorgenommen. Ich habe den JobBuilder.Create <> entfernt und ihn durch dein Beispiel ersetzt. Das Verhalten ist jedoch immer noch das gleiche. Der HelloJob wird ausgeführt, der ReleaseJob jedoch nicht. – Tomas

+0

Ich nehme an, dass die AutofacJobFactory.NewJob() -Methode jetzt aufgerufen wird? Wenn ja, ist es ein Problem mit Ihrer Bindung. Als Test können Sie die relevanten markierten Fehlerzeilen in 'builder.RegisterType .As ();' ändern und auch die nächste Zeile in 'JobDetailImpl ändern jobDetail = new JobDetailImpl (" 1Job ", null, typeof (IJob)); 'Beachten Sie, dass dies prüft, ob Bindungen jetzt gelöst werden, aber Sie benötigen eine abstrakte Factory, wenn Sie mehrere Typen von 'IJob' instanziieren möchten. – dcarson

+0

Ich habe einen Haltepunkt auf die AutofacJobFactory.NewJob() gesetzt. Es wird für den HelloJob aufgerufen, scheint aber niemals vom ReleaseJob ausgelöst zu werden. Ich änderte auch die Baumeister- und Jobtypen, die zu IJob notiert wurden und führte sie nur einzeln nacheinander aus. Der HelloJob hat wieder funktioniert, der ReleaseJob nicht. Danke für all die Hilfe, die ich bisher hatte - ich bin nicht sehr erfahren mit Bindings und habe vermutet, dass sie das Problem hier waren. Ich bin mir nicht sicher, was ich als nächstes versuchen soll, um sie zur Arbeit zu bringen. – Tomas