Почему бы просто не добавить ISession
в ваши репозитории вместо ISessionFactory
?
Вот аналогичный код, который я использую с Autofac, другим контейнером IoC:
containerBuilder
.Register(c => NHibernateContext.GetSessionFactory().OpenSession())
.As<ISession>()
.InstancePerLifetimeScope();
где NHibernateContext
- мой единственный и единственный статический класс, который настраивает NHibernate и поддерживает ISessionFactory
синглтон.
Итак, мой объект хранилища / поиска запрашивает сеанс:
public MyRepository(ISession session)
{
this.session = session;
}
Тогда мой Presenter / View Model / Superivsing Controller / «Какого черта мы это называем в этом месяце» просто получает объект хранилища или поиска:
public MyPresenter(IWhateverRepository repository)
{
// Look ma, the repository has an ISession and I'm none the wiser!
}
Я думаю, что для Виндзора (я не очень знаком с его API, вам, возможно, придется настроить его, но он должен дать вам представление), это будет что-то вроде
container.Register(
Component.For<ISession>
.UsingFactoryMethod(
x => x.Resolve<ISessionFactory>().OpenSession())
.LifeStyle.Transient);
То есть вы говорите контейнеру: «Когда кто-то просит ISession, запустите этот маленький делегат, который получает ISessionFactory
и открывает сеанс, а затем передайте ему этот ISession
экземпляр."
а кто закрывает ISession
? Это зависит от вас: вы можете сделать так, чтобы хранилище явно закрывало ISession
в своем собственном Dispose()
методе. Или вы могли бы положиться на свой контейнер, чтобы сделать закрытие и утилизацию; в Autofac я делаю это с ILifetimeScope
и InstancePerLifetimeScope()
; в Виндзоре я считаю, что вам нужно искать вложенные контейнеры, чтобы при удалении дочернего контейнера все компоненты, которые он создал, также были удалены.
По моему опыту, это обычно означает, что контейнер просачивается по крайней мере в "основную форму" моего приложения: когда приходит время создавать форму, он создает новую область действия / вложенный контейнер и показывает форму. Но ничего ниже этого уровня не знает о контейнере; это просто бросить лассо вокруг набора компонентов и сказать «избавиться от всего этого, когда форма закрыта».
(Это сделано для того, чтобы не использовать один большой сигнал ISession
в большинстве приложений. Это прекрасно работает в ASP.NET, один сеанс на запрос, но, как вы заметили, в Windows Forms это похоже на помечая бомбу замедленного действия для исключений устаревших объектов. Лучше, чтобы каждая «единица работы» (обычно каждая форма или служба) имела свою собственную ISession
.)
Вы можете альтернативно спроектировать свои репозитории так, чтобы для каждого метода требовалось передать ISession
, но, похоже, это будет утомительно.
Надеюсь, это даст вам некоторые идеи. Удачи!