Question

Je suis en train de mettre en œuvre un modèle de session par demande dans ma demande de WCF, et j'ai lu d'innombrables documents sur ce sujet, mais il semble comme il n'y a pas une démonstration complète de cela. Je suis en fait à travers des articles très utiles comme celui-ci:

NHibernate de ISession dont la portée a pour un seul WCF appel

mais ce sont tous des vieux jours où NHibernate et Ninject ne disposaient pas des implémentations spécifiques WCF, donc ils ont réalisé ce que je besoin en mettant en œuvre leurs fournisseurs de services personnalisés, etc. Étant donné que Ninject et NHibernate ont le soutien WCF maintenant, je veux garder les choses cohérentes en utilisant leurs modules, mais je me suis retrouvé ici ...

devrait être quelque chose comme la configuration de base et le débit ceci:

  1. Set CurrentSessionContext à WcfOperationSessionContext dans la configuration NHibernate
  2. Le démarrage du service, commencez demande ou partout dans le temps d'initialisation, ouverture de session et le lier au contexte actuel
  3. Référentiels obtenir l'instance en cours de session en utilisant la méthode SessionFactory.getCurrentSession ()
  4. Unbind et fermeture de session à la fin du cycle de vie

Mon problème initial était que je ne pouvais pas accéder au cycle de vie de WCF pour gérer mes fixations. Après avoir creusé dans le code ninject un peu, j'ai réussi à accrocher mes méthodes à l'ouverture de ServiceHost / Fermeture des événements sans changer beaucoup, mais je ne suis pas en mesure d'accéder à la OperationContext car il est thread-statique.

Plus tard, j'ai essayé permettant la compatibilité asp.net et l'utilisation Application_BeginRequest et Application_EndRequest, et ils avaient l'air très prometteur, mais je ne pense pas que ce soit la meilleure solution car je devrais choses se lier à l'instance de service, plutôt que la demande http.

Quelqu'un at-il jamais réalisé cela en utilisant de ninject intégré dans les bibliothèques d'extension WCF? Ou des idées sur ce que je pourrais faire mal?

Était-ce utile?

La solution

Je l'ai mis en œuvre par demande durée de session avec l'aide de IDispatchMessageInspector . Probablement que vous pourriez mettre en œuvre gestionnaire de vie personnalisé pour Ninject d'obtenir par requête web.

Autres conseils

Hy

Vous pouvez faire ce qui suit:

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

Avec que vous pouvez utiliser partout ISession sans se soucier des détails. Vous pouvez modifier InRequestScope avec InScope (CTX => OperationContext.Current) d'utiliser la portée WCF

Vous pouvez être en mesure de le faire en utilisant les points d'extension prévus dans la section Interface de IInstanceContextProvider.

scroll top