Нужна помощь в понимании того, как Ninject получает экземпляр Nhibernate SessionFactory в UnitOfWork?

#c# #asp.net-mvc-2 #dependency-injection #ioc-container #ninject

#c# #asp.net-mvc-2 #внедрение зависимостей #ioc-контейнер #ninject

Вопрос:

Итак, используя некоторую помощь из руководств, мне удалось подключить сеанс Nhibernate к моим репозиториям, а мои репозитории — к моим контроллерам, используя Ninject. Однако есть один момент настройки, из-за которого я не понимаю «автоматической магии» того, что делает Ninject, и надеялся, что кто-нибудь сможет объяснить.

Ниже приведен мой Ninject ModuleRepository, который наследуется от NinjectModule, который выполняет всю привязку.

 public class ModuleRepository : NinjectModule
{
    public override void Load()
    {
        var helper = new NHibernateHelper(ConfigurationManager.ConnectionStrings[Environment.MachineName].ConnectionString);

        Bind<ISessionFactory>().ToConstant(helper.SessionFactory)
            .InSingletonScope();

        Bind<IUnitOfWork>().To<UnitOfWork>()
            .InRequestScope();
        Bind<ISession>().ToProvider<SessionProvider>()
            .InRequestScope();
        Bind<IRepository<Product>>().To<ProductRepository>();
        Bind<IRepository<Category>>().To<CategoryRepository>();
    }
}
  

Вот класс UnitOfWork:

 public class UnitOfWork : IUnitOfWork
{
    private readonly ISessionFactory _sessionFactory;
    private readonly ITransaction _transaction;
    public ISession Session { get; private set; }

    public UnitOfWork(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;

        //Open Session
        Session = _sessionFactory.OpenSession();
        Session.FlushMode = FlushMode.Auto;
        _transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public void Commit()
    {
        if (!_transaction.IsActive)
            throw new InvalidOperationException("There is no active Transaction");
        _transaction.Commit();
    }

    public void Rollback()
    {
        if (_transaction.IsActive)
            _transaction.Rollback();
    }

    //Close open session
    public void Dispose()
    {
        Session.Close();
    }
}
  

Итак, я понимаю, что мы создаем постоянный экземпляр объекта, который создает Nhibernate SessionFactory. Ниже приведен класс SessionProvider, который возвращает сеанс из объекта UnitOfWork, который оборачивает каждую единицу работы в транзакцию.

SessionProvider

 public class SessionProvider : Provider<ISession>
{
    protected override ISession CreateInstance(IContext context)
    {
        var unitOfWork = (UnitOfWork)context.Kernel.Get<IUnitOfWork>();
        return unitOfWork.Session;
    }
}
  

Репозитории принимают ISession в своем конструкторе. Но чего я не вижу, так это того, как UnitOfWork.Session является «сеансом», который передается в мои репозитории?

Любая помощь в понимании этого была бы отличной. Спасибо.

Ответ №1:

Привязка с использованием:

 Bind<ISession>().ToProvider<SessionProvider>().InRequestScope();
  

указывает, что он должен поддерживать область запроса. Это означает, что Ninject будет кэшировать все запросы для ISession в течение всего HttpRequest — таким образом, все внедряемые классы (или явно получающие экземпляр) будут использовать один и тот же экземпляр ISession. В вашей конфигурации то же самое касается IUnitOfWork.

Смотрите Этот пост Нейта Кохари для описания различных объектов области видимости в Ninject.