Spring.NET + NHibernate + запрашивает объекты с областями видимости, которые не очень хорошо играют вместе - PullRequest
1 голос
/ 04 января 2012

Я использую Spring.NET 1.3.2, NHibernate 3.1 и шаблон OSIV в приложении ASP.NET.

У меня есть пользовательский EventListener, который должен быть запрос , потому что он использует HttpContext.Current.Items как зависимость конструктора.

Так как ISession также запрос ограничен, я должен иметь возможность использовать Spring.NET для управления этими зависимостями для меня.

Проблема в том, что EventListener, как и IInterceptor, является свойством ISessionFactory, которое не ограничено запросом (это одиночный код). Несоответствие между областями веб-объектов является проблематичным.

Я попробовал следующий фрагмент XML, но условное выражение всегда дает ноль. Я думаю, это связано с тем, что Spring создает объект EventListener на уровне приложения, и до того, как HttpContext.Current.Items сможет заполниться.

  <object id="EventListener" scope="request" type="MyEventListener,DAL">

        <constructor-arg index="0" expression="T(System.Web.HttpContext).Current.Items.Contains('Principal')?T(System.Web.HttpContext).Current.Items['Principal']:null"/>

  </object>

Итак, мое требование:

  1. Настроить пользовательский EventListener объект в Spring таким образом, чтобы он создавался для каждого запроса

  2. EventListener инстанцирование должно происходить достаточно поздно в жизненном цикле запроса, чтобы HttpContext.Current.Items ['Princpial'] был заполнен пользовательским IHttpModule

  3. Экземпляр EventListener внедряется в текущий OSIV ISession

1 Ответ

1 голос
/ 20 января 2012

Я думаю, вы пытаетесь сделать это неправильно.В соответствии с документацией NHibernate EventListener s в основном следует рассматривать как одиночные для вашего приложения.

Даже когда вы регистрируете свой пользовательский EventListener с помощью SessionFactory, скажем, в началезапрос, у вас все еще нет никакой гарантии, что этот слушатель будет только получать события, созданные в текущем HttpContext.

Вместо этого вы должны зарегистрировать ваши обработчики событий глобально, при настройке фабрики сеанса.Если вам нужна контекстная информация, такая как принципал, вы можете внедрить зависимость с помощью (http) контекстно-зависимой реализации или реализовать ее как окружающий контекст .

Из пользовательского прослушивателя вы можете получить доступ к сеансу, вызвавшему событие.Возьмем, к примеру, эту ILoadEventListener реализацию:

public class CustomLoadEventListener : ILoadEventListener
{
    private IPrincipalProvider _principalProvider;

    public CustomLoadEventListener(IPrincipalProvider provider)
    {
        _principalProvider = provider;
    }

    public void OnLoad(LoadEvent @event, LoadType loadType)
    {
        var sessionThatRaisedTheEvent = @event.Session;
        var principalForTheCurrentContext = _principalProvider.GetCurrentPrincipal();
    }
}

public interface IPrincipalProvider
{
    IPrincipal GetCurrentPrincipal();
}

public class HttpContextPrincipalProvider : IPrincipalProvider
{
    public IPrincipal GetCurrentPrincipal()
    {
        return System.Web.HttpContext.Current.User;
    }
}

Возможно, это не тот ответ, который вы надеялись получить, но IMO, о чем вы просите, будет бороться с инфраструктурой, чего я обычно стараюсь избегать.

Если вы опубликуете более подробную информацию о том, чего вы пытаетесь достичь, мы сможем предложить лучшее решение.Что должен делать EventListener

...