2011-02-01 4 views
11

WCF 응용 프로그램에서 요청 당 세션 모델을 구현하려고하는데이 주제에 대해 수많은 문서를 읽었지만 이것에 대한 완전한 시위. 실제로 이곳과 같은 몇 가지 매우 유용한 기사를 건너 왔어요 :WCF, NHibernate 및 Ninject에 대한 세션 당 요청 구현

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

하지만 이러한 자 NHibernate와 Ninject에이 WCF 특정 구현을 가지고 있지 않은 옛부터 모두 그러므로 그들은 내가 구현하여 필요한 달성 자신 커스텀 서비스 프로 바이더 등등. Ninject와 NHibernate는 모두 WCF를 지원하기 때문에 모듈을 사용하여 일들을 일관성있게 유지하고 싶습니다. 그러나 여기까지 왔습니다 ...

기본 설정과 흐름은 다음과 같아야합니다 :

  1. 설정 요청을 시작, 또는 그 밖의 초기화시기, 개방 세션
  2. 저장소가 SessionFactory.GetCurrentSession를 사용하여 현재 세션 인스턴스를 가져 현재 컨텍스트에 바인딩, 서비스 시작에
  3. NHibernate에 구성 WcfOperationSessionContext에의 CurrentSessionContext() 방법
  4. 바인딩 해제 및 내 바인딩을 처리하는 WCF 라이프 사이클에 액세스 할 수 없음을주기

내 초기 문제가 있었다의 끝 부분에 가까운 세션. ninject 코드를 파고 들자 조금 변경하지 않고 ServiceHost의 Opening/Closing 이벤트에 내 메서드를 연결했지만 Thread-static이기 때문에 OperationContext에 액세스 할 수 없었습니다.

나중에 asp.net 호환성을 활성화하고 Application_BeginRequest 및 Application_EndRequest를 사용하여 시도했지만 매우 유용하다고 보았습니다.하지만 http 요청이 아닌 서비스 인스턴스에 바인딩해야하므로 최선의 해결책이라고 생각하지 않습니다. .

누구든지 ninject에 내장 된 wcf 확장 라이브러리를 사용하여 이것을 달성 했습니까? 또는 내가 뭘 잘못하고 있는지에 대한 아이디어가 있습니까?

답변

2

IDispatchMessageInspector의 도움으로 요청 세션 당 유효 기간을 구현했습니다. 아마도 웹 요청 당 달성하기 위해 Ninject 용 사용자 정의 평생 관리자를 구현할 수 있습니다.

+0

감사합니다. 내가 IDispatchMessageInspector에 대해 읽고 있던 나는이 구현 발견 : 약간의 비틀기와 https://igloocoder.net:8443/svn/IglooCommons/trunk/src/IglooCoder.Commons/WcfNhibernate/ 을, 나는 그것을 할 수 있었다 작업. – salimaabey

+0

링크가 지금까지 불행히도 망가졌습니다. :( – Cornelius

1

숨바꼭질

다음과 같은 작업을 수행 할 수 있습니다 그와

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를 사용할 수 있습니다. InScope (ctx => OperationContext.Current)로 InRequestScope를 편집하여 WCF 범위를 사용할 수 있습니다.