3

ASP.NET MVC アプリで NHIbernate と共に IoC に Castle Windsor を使用しています。次のように登録するとうまく機能します(1つの例外を除く):

container.Register(Component.For<ISessionFactoryBuilder.().ImplementedBy<SessionFactoryBuilder>().LifestyleSingleton());

// Register the NHibernate session factory as a singleton using custom SessionFactoryBuilder.BuildSessionFactory method.
container.Register(Component.For<ISessionFactory>().UsingFactoryMethod(k => k.Resolve<ISessionFactoryBuilder>().BuildSessionFactory("ApplicationServices")).LifestyleSingleton());

container.Register(Component.For<IInterceptor>().ImplementedBy<ChangeAuditInfoInterceptor>().LifestylePerWebRequest());
container.Register(Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>()
            .OpenSession(container.Resolve<IInterceptor>())).LifestylePerWebRequest()); 

ChangeAuditInterceptor に IAccountSession サービスが注入され、これに NHibernate ISession が注入されていることを除いて、すべて問題ありません...これにより、次の循環依存例外が発生します。

コンポーネント 'Late bound NHibernate.ISession' を解決しようとしたときに、依存サイクルが検出されました。循環の結果となった解決ツリーは次のとおりです: コンポーネント 'Late bound NHibernate.ISession' は、コンポーネント 'Blah.Core.Services.AccountSession' の依存関係として解決されました コンポーネント 'Blah.Core.Infrastructure.Data.ChangeAuditInfoInterceptor' の依存関係として解決されましたコンポーネント 'Blah.Core.Infrastructure.Installers.SessionFactoryBuilder' の依存関係として解決されました コンポーネント '遅延バインド NHibernate.ISessionFactory' の依存関係として解決されました 解決されるルート コンポーネントであるコンポーネント '遅延バインド NHibernate.ISession' の依存関係として解決されました。

過去数年間、私は通常、この循環依存の問題を引き起こすことなく、IInterceptor でプランクを処理する NHibernateSessionManager を使用して実行してきました (Castle Windsor の UsingFactoryMethod 機能を使用する SessionFactoryBuilder の使用法とは対照的に)。

この循環依存を解決する方法について何か提案はありますか? 他の手段を介して AccountSession の ISession をハッキングし始めるまではありません (つまり、問題を回避し、結果として悪臭を放つプロパティ インジェクション)。AccountSession サービスの ISession インジェクションをプロパティ インジェクションに切り替えましたが、正常に動作しますが、暗黙的なコントラクトとコンストラクターの明示的なコントラクトが好きではありません。

public class AccountSession : IAccountSession
{
    private readonly ISession _session;

    public AccountSession(ISession session)
    {
        _session = session;
    }

    public Account GetCurrentAccount() // Called by a method in ChangeAuditInterceptor
    {
...
    }

...等。

4

1 に答える 1

4

インターセプター クラスに Func< ISession > への依存関係を追加してみてください

public class CustomInterceptor : EmptyInterceptor
{
    private readonly Func<ISession> sessionFunc;
    private ISession session;

    protected ISession Session
    {
        get
        {
            return session ?? (session = sessionFunc());
        }
    }

    public CustomInterceptor(Func<ISession> sessionFunc)
    {
        this.sessionFunc = sessionFunc;
    }
}

そして登録:

container.Register(Component.For<ISession>().
    LifestylePerWebRequest()
    .UsingFactoryMethod(container =>
    {
        var interceptor = container.Resolve<IInterceptor>();
        return container.Resolve<ISessionFactory>.OpenSession(interceptor);
    }));
container.Register(Component.For<Func<ISession>>()
    .LifestylePerWebRequest()
    .UsingFactoryMethod(container =>
    {
        Func<ISession> func = container.Resolve<ISession>;
        return func;
    }));
于 2013-08-22T13:57:31.217 に答える