5 votes

Quartz.NET, NH ISession et Ninject Scope

J'essaie d'implémenter un service qui va exécuter des tâches basées sur Quartz.Net. Les tâches peuvent avoir des dépendances comme IRepository<> et l'implémentation du dépôt aura un NHibernate ISession injecté dedans. (Quartz sera hébergé dans un service Windows). Les travaux sont résolus via une mise en œuvre de la fabrique IJob qui utilise Ninject pour résoudre (actuellement enveloppé dans une mise en œuvre IServiceLocator).

Portée du travail

J'aimerais pouvoir utiliser Ninject pour étendre l'ISession par tâche de sorte qu'il y ait une session créée par tâche qui puisse être utilisée dans plusieurs IRepository<>'s.

Je ne sais pas si c'est possible, mais je me demande si quelqu'un a une expérience dans ce domaine.

Puis-je, d'une manière ou d'une autre, utiliser le contexte du travail pour créer un scope qui sera utilisé par 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;
        }
    }
}

Fixations Ninject :

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

Exécution principale :

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

Exemple d'emploi :

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

Merci de prendre le temps !

Mise à jour J'ai fini par suivre la suggestion de Remo et j'utilise InCallScope() :

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

La façon dont je vois les choses (correcte ou non ?) est que tout ce qui est obtenu à partir de l'obtention "initiale" réutilise les mêmes éléments tout au long de l'arbre de dépendance.

2voto

Remo Gloor Points 26195

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X