2011-02-01 14 views
11

Estoy tratando de implementar un modelo de sesión por solicitud en mi aplicación WCF, y he leído innumerables documentos sobre este tema, pero parece que no hay un completa demostración de esto. De hecho, me encontré con algunos artículos muy útiles como este:implementación de sesión por solicitud para WCF, NHibernate y Ninject

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

pero todos ellos son de los viejos tiempos, cuando NHibernate y Ninject no tienen implementaciones específicas de WCF, por lo tanto, que lograron lo que necesito por la aplicación de su proveedores de servicios personalizados, etc. Dado que tanto Ninject como NHibernate tienen soporte WCF ahora, quiero mantener las cosas consistentes utilizando sus módulos, pero terminé aquí ...

La configuración básica y el flujo deberían ser algo como esto:

  1. Conjunto CurrentSessionContext a WcfOperationSessionContext en la configuración nhibernate
  2. En la puesta en servicio, iniciar la solicitud, o en cualquier lugar en todo el tiempo de inicio, la sesión abierta y enlazarlo al contexto actual
  3. repositorios obtener la instancia de sesión actual utilizando SessionFactory.getCurrentSession() método
  4. Unbind y cerca de sesión al final del ciclo de vida

Mi problema inicial era que yo no era capaz de acceder al ciclo de vida de WCF para manejar mis ataduras. Después de profundizar un poco en el código de ninject, logré conectar mis métodos a los eventos de Apertura/Cierre de ServiceHost sin cambiar mucho, pero luego no pude acceder al OperationContext porque es thread-static.

Más tarde probé la compatibilidad con asp.net y el uso de Application_BeginRequest y Application_EndRequest, y parecía muy prometedor, pero no creo que sea la mejor solución ya que debería enlazar cosas a la instancia del servicio, en lugar de la solicitud http .

¿Alguien ha logrado esto utilizando las bibliotecas de extensión de wcf integradas de ninject? ¿O alguna idea sobre lo que podría estar haciendo mal?

Respuesta

2

He implementado por período de vida de la sesión de solicitud con la ayuda de IDispatchMessageInspector. Probablemente podría implementar administrador de por vida personalizado para Ninject para lograr por solicitud web.

+0

Tenía razón, gracias. Estaba leyendo sobre IDispatchMessageInspector y me encontré con esta implementación: https://igloocoder.net:8443/svn/IglooCommons/trunk/src/IglooCoder.Commons/WcfNhibernate/ Con algunos ajustes menores, yo era capaz de hacerlo trabajo. – salimaabey

+0

El enlace está, lamentablemente, roto. :( – Cornelius

1

Hy

Usted puede hacer lo siguiente:

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

Con que se puede utilizar en todas partes ISession sin preocuparse por los detalles. Puede editar InRequestScope con InScope (ctx => OperationContext.Current) para usar el alcance de WCF

Cuestiones relacionadas