Sto cercando di implementare un servizio che eseguirà i lavori basati su Quartz.Net. I lavori possono avere dipendenze come IRepository <> e l'implementazione del repository avrà in esso una iniezione NHibernate. (Quartz sarà ospitato in un servizio di Windows). I lavori vengono risolti tramite un'implementazione di fabbrica IJob che utilizza Ninject per risolvere (attualmente racchiuso in un'implementazione di IServiceLocator).Quartz.NET, NH ISession & Ninject Scope
Ambito lavoro
Mi piacerebbe essere in grado di utilizzare Ninject al campo di applicazione ISession per lavoro in modo che ci sia una sessione creato per ogni lavoro che può essere utilizzato in più IRepository <> s '.
Non so se è possibile, ma mi chiedo se qualcuno ha esperienza con questo?
Posso in qualche modo utilizzare il contesto di lavoro per creare un ambito utilizzato da 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 Attacchi:
//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<>));
esecuzione principale:
InitializeIoC();
scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = ServiceLocator.Resolve<IJobFactory>();
InitializeJobs();
scheduler.Start();
Esempio di lavoro:
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
}
** Repository Snippet: **
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;
}
}
Grazie per aver dedicato del tempo!
Aggiornamento ho finito per usare il suggerimento di Remo e sto usando InCallScope():
Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession()).InCallScope();
Il modo in cui mi piace pensare di esso (? Corretto o meno) è tutto dalla "prima" get riutilizza gli stessi articoli in tutto l'albero delle dipendenze
Puoi pubblicare la tua soluzione? Sono dello stesso problema –