2011-02-01 11 views
11

Próbuję zaimplementować model sesji na żądanie w mojej aplikacji WCF i przeczytałem niezliczone dokumenty na ten temat, ale wygląda na to, że nie ma pełna demonstracja tego. I rzeczywiście natknąłem się kilka bardzo przydatnych artykułów takich jak ten:Implementacja sesji na żądanie dla WCF, NHibernate i Ninject

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

ale to wszystko z dawnych czasów, kiedy NHibernate i Ninject nie mają WCF konkretne realizacje, dlatego osiąga to, czego potrzebuję, wdrażając ich niestandardowych dostawców usług, itp. Ponieważ teraz zarówno Ninject, jak i NHibernate mają wsparcie WCF, chcę zachować spójność przy użyciu ich modułów, ale skończyłem tutaj ...

Podstawowa konfiguracja i przepływ powinien wyglądać następująco:

  1. Set CurrentSessionContext do WcfOperationSessionContext w NHibernate konfiguracji
  2. Na początku służby, zaczynają wniosek, lub w dowolnym miejscu na czas init otwarta sesja i powiązać go z obecnym kontekście
  3. Repozytoria uzyskać bieżące wystąpienie sesji korzystając SessionFactory.GetCurrentSession() metoda
  4. Unbind i blisko sesja na koniec cyklu

Moja początkowa problemem było to, że nie był w stanie uzyskać dostęp do cyklu wCF obsłużyć moje wiązania. Po kilkukrotnym wykopaniu kodu, udało mi się podłączyć moje metody do zdarzeń otwierania/zamykania ServiceHost bez zmiany wielu, ale wtedy nie byłem w stanie uzyskać dostępu do OperationContext, ponieważ jest to wątek statyczny.

Później próbowałem włączyć kompatybilność asp.net i używając Application_BeginRequest i Application_EndRequest i wyglądało to bardzo obiecująco, ale nie sądzę, że jest to najlepsze rozwiązanie, ponieważ powinienem wiązać rzeczy do instancji usługi, a nie żądania http .

Czy ktoś kiedykolwiek osiągnął to za pomocą wbudowanych bibliotek rozszerzonych wcf? Albo jakieś pomysły na temat tego, co robię źle?

Odpowiedz

2

Zaimplementowałem na czas życia sesji żądania za pomocą IDispatchMessageInspector. Prawdopodobnie mógłbyś zaimplementować niestandardowy menedżer życia dla Ninject, aby osiągnąć na żądanie WWW.

+0

Miałeś rację, dziękuję. Czytałam o IDispatchMessageInspector i znalazłem ten realizacji: https://igloocoder.net:8443/svn/IglooCommons/trunk/src/IglooCoder.Commons/WcfNhibernate/ z niewielkimi szczypie, byłem w stanie to zrobić praca. – salimaabey

+0

Link jest, niestety, uszkodzony. :( – Cornelius

1

Hy

można wykonać następujące czynności:

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; 
     } 
    } 
} 

Dzięki czemu można używać wszędzie ISession bez dbałości o szczegóły. Możesz edytować InRequestScope za pomocą InScope (ctx => OperationContext.Current), aby użyć zakresu WCF

Powiązane problemy