2011-02-01 27 views
11

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

NHibernate's ISession, scoped for a single WCF-call

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

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

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

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

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

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

ответ

2

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

+0

Вы были правы, спасибо. Я читал о IDispatchMessageInspector, и я нашел эту реализацию: https://igloocoder.net:8443/svn/IglooCommons/trunk/src/IglooCoder.Commons/WcfNhibernate/ С некоторыми незначительными твиков, я был в состоянии сделать это Работа. – salimaabey

+0

Ссылка сейчас, к сожалению, сломана. :( – Cornelius

0

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

1

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.