nhibernateviewmodelninjectcaliburnisession

Create an instance of ISession per ViewModel


here is my problem: I'm building a desktop application, with the following tools:

All my view models and repositories are instanciated with Ninject. My repositories all need an ISession in their constructor.

I'd like to follow ayende's advice concerning the ViewModels: each ViewModel opens a new session.

Is it possible to configure Ninject to open a new session when a ViewModel is created, and use this session inside the repositories used by this view model?

I had a look to the InScope function of Ninject, as well as the ICurrentSessionContext interface in NHibernate, but I don't know how to model all of that to get what I want...

Did someone make something like that before?

Thanks in advance

Mike


Solution

  • Well, I've found a solution thanks to the ninject group.

    The solution here is to use the function InScope when I bind ISession, and browse in the IContext variable to inspect the services. If one service in the request hierarchy is assignable to the base class of my view models, I use the context as scope.

    So the first time an ISession will be injected in the constructor of my ViewModel, a new scope is used. And all subsequent calls to ISession inside the constructor of the ViewModel will be resolved with the same scope. And then only one session is created for my ViewModel.

    Here is the code:

    Bind<ISession>().ToMethod(ctx =>
        {
            var session = ctx.Kernel.Get<INHibernateSessionFactoryBuilder>()
                .GetSessionFactory()
                .OpenSession();
    
            session.FlushMode = FlushMode.Commit;
    
            return session;
        })
        .InScope(ctx =>
        {
            var request = ctx.Request;
    
            if (request.Service is IScreen)
                return request;
    
            while ((request = request.ParentRequest) != null)
                if (typeof(IScreen).IsAssignableFrom(request.Service))
                    return request;
    
            return new object();
        });
    

    And the constructor of the viewmodel must contains all the injected dependencies which rely on the ISession:

    [Inject]
    public PlayersManagementViewModel(ISession session, IPlayersRepository playersRepository)
    {
    }
    

    Hope that helps