11

WCFアプリケーションにリクエストごとのセッションモデルを実装しようとしています。このトピックに関する無数のドキュメントを読みましたが、これの完全なデモンストレーションがないようです。私は実際にこのようないくつかの非常に有用な記事に出くわしました:

NHibernateのISession、単一のWCF呼び出しを対象

しかし、これらはすべてNHibernateとNinjectにWCF固有の実装がなかった昔のものであり、カスタムサービスプロバイダーなどを実装することで私が必要とするものを達成しました。NinjectとNHibernateの両方が現在WCFをサポートしているので、一貫性を保ちたいと思います。それらのモジュールを使用することによって、しかし私はここに行き着きました...

基本的なセットアップとフローは次のようになります。

  1. nhibernate構成でCurrentSessionContextをWcfOperationSessionContextに設定します
  2. サービスの開始時、リクエストの開始時、または初期化時間の前後の任意の場所で、セッションを開き、現在のコンテキストにバインドします
  3. リポジトリは、SessionFactory.GetCurrentSession()メソッドを使用して現在のセッションインスタンスを取得します
  4. ライフサイクルの最後にセッションのバインドを解除して閉じます

私の最初の問題は、バインディングを処理するためにwcfライフサイクルにアクセスできなかったことでした。ninjectコードを少し掘り下げた後、あまり変更せずにServiceHostのOpening / Closingイベントにメソッドをフックすることができましたが、スレッド静的であるため、OperationContextにアクセスできませんでした。

後で、asp.net互換性を有効にして、Application_BeginRequestとApplication_EndRequestを使用しようとしましたが、非常に有望に見えましたが、httpリクエストではなく、サービスインスタンスにバインドする必要があるため、これが最善の解決策ではないと思います。

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

4

3 に答える 3

2

IDispatchMessageInspectorを使用して、リクエストごとのセッションの有効期間を実装しました。おそらく、Ninject のカスタム ライフタイム マネージャーを実装して、Web リクエストごとに達成することができます。

于 2011-02-02T07:56:12.620 に答える
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スコープを使用できます。

于 2011-06-02T14:21:22.883 に答える
0

IInstanceContextProviderインターフェイスで提供される拡張ポイントを使用することで、それを実行できる場合があります。

于 2011-02-02T07:16:57.943 に答える