реализация сеанса для запроса для WCF, NHibernate и Ninject - PullRequest
11 голосов
/ 01 февраля 2011

Я пытаюсь реализовать модель сеанса на запрос в своем приложении WCF, и я прочитал бесчисленные документы по этой теме, но похоже, что это не полная демонстрация этого. Я действительно наткнулся на несколько очень полезных статей, таких как эта:

ISession NHibernate, ограниченный для одного WCF-вызова

но это все из тех давних времен, когда NHibernate и Ninject не имели конкретных реализаций WCF, поэтому они достигли того, что мне нужно, за счет реализации своих пользовательских провайдеров услуг и т. Д. Поскольку и Ninject, и NHibernate имеют поддержку WCF сейчас, я хочу сохраняйте согласованность, используя их модули, но я оказался здесь ...

Базовая настройка и поток должны быть примерно такими:

  1. Установите для CurrentSessionContext значение WcfOperationSessionContext в конфигурации nhibernate
  2. При запуске службы, запросе на начало или где-либо еще во время инициализации откройте сеанс и привяжите его к текущему контексту
  3. Репозитории получают текущий экземпляр сеанса, используя метод SessionFactory.GetCurrentSession ()
  4. Отмена привязки и закрытие сессии в конце жизненного цикла

Моя первоначальная проблема заключалась в том, что я не мог получить доступ к жизненному циклу wcf для обработки своих привязок. Немного покопавшись в недействительном коде, мне удалось без особых изменений привязать свои методы к событиям открытия / закрытия ServiceHost, но затем я не смог получить доступ к OperationContext, так как он является статичным для потока.

Позже я попытался включить совместимость с asp.net и использовать Application_BeginRequest и Application_EndRequest, и это выглядело очень многообещающе, но я не думаю, что это лучшее решение, так как я должен связывать вещи с экземпляром службы, а не с запросом http.

Кто-нибудь когда-нибудь достигал этого, используя встроенные в nincject библиотеки расширений wcf? Или есть идеи о том, что я могу делать неправильно?

Ответы [ 3 ]

2 голосов
/ 02 февраля 2011

Я реализовал время жизни сеанса запроса с помощью IDispatchMessageInspector . Возможно, вы могли бы реализовать собственный диспетчер времени жизни для Ninject, который можно получить для каждого веб-запроса.

1 голос
/ 02 июня 2011

Hy

Вы можете сделать следующее:

public class DomainModule : NinjectModule
{
    private const string RealSessionIndicator = "RealSession";

    private readonly ProxyGenerator proxyGenerator = new ProxyGenerator();

    public override void Load()
    {
        this.Bind<ISession>().ToMethod(ctx => ctx.Kernel.Get<ISessionFactory>().OpenSession())
            .When(r => r.Parameters.Any(p => p.Name == RealSessionIndicator))
            .InRequestScope();

        this.Bind<Func<ISession>>().ToMethod(ctx => () => ctx.Kernel.Get<ISession>(new Parameter(RealSessionIndicator, (object)null, true)));

        this.Bind<ISession>()
            .ToMethod(this.CreateSessionProxy)
            .InTransientScope();

        this.Bind<ISessionFactory>().ToMethod(ctx => ctx.Kernel.Get<Configuration>().BuildSessionFactory()).InSingletonScope();
    }

    private ISession CreateSessionProxy(IContext ctx)
    {
        var session = (ISession)this.proxyGenerator.CreateInterfaceProxyWithoutTarget(typeof(ISession), new[] { typeof(ISessionImplementor) }, ctx.Kernel.Get<SessionInterceptor>());
        return session;
    }
}

public class SessionInterceptor : IInterceptor
{
    private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    private readonly Func<ISession> sessionProvider;

    public SessionInterceptor(Func<ISession> sessionProvider)
    {
        this.sessionProvider = sessionProvider;
    }

    public void Intercept(IInvocation invocation)
    {
        try
        {
            var session = this.sessionProvider();
            invocation.ReturnValue = invocation.Method.Invoke(session, invocation.Arguments);
        }
        catch (TargetInvocationException exception)
        {
            Log.Error(exception);
            throw;
        }
    }
}

С этим вы можете использовать ISession везде, не заботясь о деталях. Вы можете редактировать InRequestScope с помощью InScope (ctx => OperationContext.Current), чтобы использовать область видимости WCF

0 голосов
/ 02 февраля 2011

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

...