StructureMap: вопрос CacheBy(InstanceScope.Singleton)

У меня есть вопрос о том, как работает InstanceScope.Singleton, потому что здесь я получаю неожиданные результаты:

У меня есть служба, которая зависит от Дао

public MetaProjectService(IMetaProjectDao metaProjectDao)
        {
            _metaProjectDao = metaProjectDao;

        }

и у меня есть Dao, который зависит от ISession (Nhibernate)

 public MetaProjectDao(ISession nhSession)
            : base(nhSession)
        {}

и для карты структуры у меня есть следующее:

ForRequestedType<IMetaProjectService>()
                .TheDefaultIsConcreteType<MetaProjectService>();
                    //.CacheBy(InstanceScope.Singleton);


ForRequestedType<IMetaProjectDao>()
                //.TheDefaultIsConcreteType<MetaProjectDao>()
                 //.CacheBy(InstanceScope.Singleton)
                 .TheDefault
                    .Is.ConstructedBy(() =>
                    {
                        var session = ObjectFactory
                            .GetNamedInstance<ISessionFactory>(
                            MetaProjectDao.SESSION_FACTORY_NAME)
                            .GetCurrentSession();
                        return new MetaProjectDao(session);
                    });

Вопрос. Если я раскомментирую определение для кэширования IMetaProjectService как InstanceScope.Singleton, оно не будет работать при последующих запросах, поскольку по-прежнему будет содержать ссылку на сборку экземпляра IMetaProject при первом запросе. Есть и другие зависимости, которые я опустил для ясности. Итак, вопрос заключается в том, как мне создать IMetaProjectDao для каждого запроса и сделать так, чтобы на этот новый экземпляр ссылался IMetaProjectService, имея IMetaProjectService как singleton.


person epitka    schedule 24.12.2009    source источник


Ответы (1)


После прочтения вашего кода и понимания NHibernate все работает именно так, как ожидалось.

var session = ObjectFactory
    .GetNamedInstance<ISessionFactory>(MetaProjectDao.SESSION_FACTORY_NAME)
    .GetCurrentSession();

Будет вызываться только один раз, если вы кешируете IMetaProjectDao как синглтон, чего вам НЕ ХОЧЕТСЯ. Одноэлементный экземпляр ISession из NHibernate является самым большим анти-шаблоном, который вы можете реализовать (если только это не WinForms, в чем я сомневаюсь из-за вашего использования GetCurrentSession()). Вы должны кэшировать свой Dao либо в Hybrid, либо в HybridSession, в зависимости от того, реализуете ли вы сеанс для каждого запроса или длинные сеансы.

person Chris Marisic    schedule 26.12.2009
comment
Спасибо, Крис, я знаю, что это абсолютно невозможно с ISession. Я думаю, я не осознавал (не думал ясно), что если сделать Dao singleton, ссылка на ISession никогда не будет обновлена. - person epitka; 26.12.2009
comment
Кроме того, на самом деле я делал не синглтон Dao, а Service, но это то же самое, только на уровень выше. - person epitka; 26.12.2009