2012-03-07 8 views
5

Estoy tratando de implementar un servicio que ejecutará trabajos basados ​​en Quartz.Net. Los trabajos pueden tener dependencias como IRepository <> y la implementación del repositorio tendrá un NHibernate ISession inyectado en él. (Quartz estará alojado en un servicio de Windows). Los trabajos se resuelven a través de una implementación de fábrica de IJob que utiliza Ninject para resolver (actualmente incluido en una implementación de IServiceLocator).Quartz.NET, NH ISession & Ninject Scope

Ámbito de empleo

Me gustaría ser capaz de utilizar Ninject al alcance del ISession por puesto de trabajo de manera que hay una sesión creada por puesto de trabajo que puede ser utilizado en múltiples IRepository <> 's.

No estoy seguro si esto es posible, pero me pregunto si alguien tiene experiencia con esto?

¿Puedo de alguna manera utilizar el contexto de trabajo para crear un ámbito que Kernel.InScope (???).

Quartz.Net IJobFactory:

public class JobFactory : IJobFactory 
{ 
    readonly IServiceLocator locator; 

    public JobFactory(IServiceLocator locator) 
    { 
     this.locator = locator; 
    } 

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

      return (IJob)locator.Resolve(jobType); 
     } 
     catch (Exception e) 
     { 
      var se = new SchedulerException("Problem instantiating class", e); 
      throw se; 
     } 
    } 
} 

Ninject enlaces:

 //Service Locator 
     Bind<IServiceLocator>().To<NinjectAdapter>(); 

     //Quartz Bindings 
     Bind<IJobFactory>().To<JobFactory>(); 

     //NHibernate Bindings 
     Bind<ISessionFactory>().ToMethod(ctx => ctx.Kernel.Get<NHibernateConfiguration>().BuildSessionFactory()).InSingletonScope(); 
     Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession());// ToDo: Figure out how to scope session 

     //Repository Bindings 
     Bind(typeof (IRepository<>)).To(typeof (ReadWriteRepository<>)); 

Ejecución principal:

 InitializeIoC(); 
     scheduler = schedulerFactory.GetScheduler(); 
     scheduler.JobFactory = ServiceLocator.Resolve<IJobFactory>(); 
     InitializeJobs(); 
     scheduler.Start(); 

Ejemplo de empleo:

public class TestJob3 : IJob 
{ 
    private readonly IRepository<Customer> repo; 
    private readonly IRepository<Order> orderRepo; 

    public TestJob3(IRepository<Customer> repo, IRepository<Order> orderRepo) 
    { 
     //orderRepo and repo should have the same ISession 

     this.repo = repo; 
     this.oderRepo = orderRepo; 
     System.Diagnostics.Debug.WriteLine("Job 3 Created"); 
    } 

    #region Implementation of IJob 

    public void Execute(IJobExecutionContext context) 
    { 
     System.Diagnostics.Debug.WriteLine("Job 3 Executing"); 
     using (var scope = new TransactionScope()) 
     { 
      var customer = repo.GetById(1); 
      customer.Name = "Blue Goats"; 
      repo.Save(customer); 
      scope.Complete(); 
     } 
    } 

    #endregion 
} 

** Repositorio Fragmento: **

public class ReadWriteRepository<TEntity> : IRepository<TEntity> where TEntity : class, IRootEntity 
{ 
    private readonly ISession session; 

    public ReadWriteRepository(ISession session) 
    { 
     this.session = session; 
    } 

    public virtual TEntity GetById(int id) 
    { 
     var entity = session.Get<TEntity>(id); 
     return entity; 
    } 

    public virtual TEntity Save(TEntity entity) 
    { 
     session.SaveOrUpdate(entity); 
     return entity; 
    } 
} 

Gracias por tomarse el tiempo!

actualización Terminé usando la sugerencia de Remo y estoy usando InCallScope():

Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession()).InCallScope(); 

La forma en que me gusta pensar en él (? Correcta o no) es todo, desde la "inicial" llegar reutiliza los mismos elementos a lo largo del árbol de dependencias

+1

¿Puedes publicar tu solución? Estoy con el mismo problema. –

Respuesta

2
+0

Actualmente estoy usando un Bloque de Activación que parece estar funcionando pero intentaré con la extensión InCallScope. ¡Gracias! –

+0

Remo, ¿puedes publicar tu solución usando el Bloque de Activación? –

+0

@MuriloLima No tengo una solución para esto usando el Bloque de activación. Yo no usaría eso. –