2011-02-01 8 views
11

私はWCFアプリケーションで要求ごとのセッションモデルを実装しようとしていますが、このトピックについては無数のドキュメントを読みましたが、これの完全なデモンストレーション。したがって、彼らは私が彼らを実装することにより、必要なものを達成し、WCF、NHibernate、およびNinjectのためのセッションごとの要求の実装

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

が、NHibernateはとNinjectは、WCF固有の実装を持っていなかったときに、これらはすべて昔からある:私は実際に、このようなこの1のようないくつかの非常に有用な物品に出くわしましたカスタムサービスプロバイダなどNinjectとNHibernateの両方でWCFサポートが提供されているので、モジュールを使用して一貫性を維持したいと思いますが、ここで終わりです。

基本設定とフローは次のようになります。

  1. 設定NHibernateの構成でWcfOperationSessionContextにCurrentSessionContext
  2. サービス開始で、要求を開始し、またはどこかのinit頃、オープンセッションと
  3. リポジトリはSessionFactory.GetCurrentSessionを(使用して、現在のセッションのインスタンスを取得し、現在のコンテキストにバインド)方法
  4. バインド解除と密接なセッションライフサイクル

の終わりに私の最初の問題は、私は私のバインディングを処理するために、WCFのライフサイクルにアクセスすることができないということでした。ちょっとしたコードを掘り下げた後、私はServiceHostのOpening/Closingイベントに変更を加えることなくメソッドをフックすることができましたが、それはスレッド静的なのでOperationContextにアクセスできませんでした。

その後、私はasp.net互換性を有効にしてApplication_BeginRequestとApplication_EndRequestを使用してみましたが、非常に有望でしたが、httpリクエストではなくサービスインスタンスにバインドする必要があるため、 。

ninjectの組み込みwcf拡張ライブラリを使用してこれまでに達成したことはありますか?私が間違っているかもしれないことについてのアイデアは?

答えて

2

私はIDispatchMessageInspectorの助けを借りてリクエストセッションの有効期間を実装しました。 NinjectのカスタムライフタイムマネージャをWebリクエストごとに実装することもできます。

+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を使用することができます。あなたはInScope(ctx => OperationContext.Current)でInRequestScopeを編集してWCFスコープを使用することができます

関連する問題