0

Dao と IoC という新しいパターンを試すサンプル プロジェクトを作成しました。

My Dao は次のように定義されています。

public class Dao<T> : IDao<T>
{
    protected NHibernate.ISessionFactory _sessionFactory;

    public Dao(NHibernate.ISessionFactory sessionFactory)
    {
        this._sessionFactory = sessionFactory;
    }

    protected NHibernate.ISession Session
    {
        get { return _sessionFactory.GetCurrentSession(); }
    }

    public T GetById(object id)
    {
        return Session.Get<T>(id);
    }

    ...
}

そして、対応するインストーラーがあります:

public class DaoInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For(typeof(Data.IDao<>))
            .ImplementedBy(typeof(Data.Dao<>))
            .ServiceOverrides(ServiceOverride.ForKey("SessionFactory").Eq("FirstSessionFactory"))
            .Named("FirstDao"));
    }
}

MVC パターンを使用して、引数として受け入れるコンストラクターを持つコントローラーを定義できますIDao<MyClass> myClass。Windsor は、正しい SessionFactory を使用して Dao をインスタンス化するすべての魔法を実行します。私の質問は、非 MVC 環境で同じ動作を実現するにはどうすればよいですか? では、特定のページで myClass のインスタンスを取得するにはどうすればよいでしょうか?

4

2 に答える 2

2

MVCより前は、ASP.NetはIoCパターンを使用するように構築されていませんでした。MVCはIoCに対応しており、Windsorおよびその他のIoC実装をMVCフレームワークにプラグインして、MVCのデフォルトのファクトリから完全に構成されたコントローラーをインスタンス化するタスクを引き継ぐことができる拡張ポイントがあります。Webフォームサイトには、ページクラスをインスタンス化するような機能はありません。

WebフォームプロジェクトでNHibernateを使用するには、HttpRequestのItemsコレクションを使用する必要があります。通常、リクエストがPageクラスによって処理される前後にコードを実行するHttpModuleを使用します。リクエストの開始時に、モジュールはNHibernateセッションを作成し、それをリクエストのItemsコレクション(ASP.Netに配置できる唯一の場所)に配置します。次に、ページ上のコードをセッションで取得できます。ページクラスは、必要に応じてIDao実装をインスタンス化し、それにセッションを渡します。リクエストの最後に、モジュール内のコードがセッションをフラッシュして閉じます。これにより、すべてのセッション管理がページハンドラーのコードに対して透過的に処理されます。(これは、MVCとSharp Architectureフレームワークに切り替える前に行ったことです。多くのインフラストラクチャコードを正しく取得するのは困難でした。私は、代わりにSharpArchitectureを使用できるようになりました。それはよく考えられており、私のものよりも多くの目を持っています。)

WebフォームプロジェクトでIoCコンテナを引き続き使用できますが、完全に透過的ではありません。IDaoの実装をコンテナに明示的に要求できます。IDao実装にISession実装を提供するようにIoCコンテナーを構成し、Web要求ごとのセマンティクスでセッションの存続期間を管理するように構成する必要があります。ただし、コントローラーにこのためのコードがないMVCの場合ほどクリーンではありません。

于 2011-06-20T22:08:04.587 に答える
0

回答ありがとうございます。残念なことに、私はこの分野に慣れていないため (時間は非常に限られています)、以前よりもさらに混乱しています。私が理解したことから、WebフォームはIoCで使用することを意図しておらず、回避策はありますが、かなり複雑です。プロジェクトを MVC に移行するまで、Windsor を放棄すると思います。今のところ、単純な静的SessionManagerクラスを利用しています。

SessionFactoriesContainerSessionManager は、次のように定義された App_Init 中のインスタンス化を担当します。

public static readonly Dictionary<string, ISessionFactory> SessionFactoriesContainer = new Dictionary<string, ISessionFactory>();

次のようにSessionsContainer定義されます。

public static Dictionary<string, ISession> SessionsContainer
    {
        get
        {
            Dictionary<string, ISession> sessionContainer = (Dictionary<string, ISession>)HttpContext.Current.Items[SESSION_CONTAINER_KEY] ?? new Dictionary<string, ISession>();
            foreach (FactoryType type in Enum.GetValues(typeof(FactoryType)))
            {
                if (!sessionContainer.ContainsKey(type.ToString()))
                    sessionContainer.Add(type.ToString(), null);
            }
            HttpContext.Current.Items[SESSION_CONTAINER_KEY] = sessionContainer;
            return sessionContainer;
        }
    }

静的ですがSessionsContainer、HttpContext に格納されているため、各ユーザーには独自のコンテナーがあると理解していますが、これを想定するのは間違っていますか?

SessionManager には、次のGetSessionForように定義されたクラスもあります。

public static ISession GetSessionFor(FactoryType type)
    {
        ISession session = SessionsContainer[type.ToString()] ?? SessionFactoriesContainer[type.ToString()].OpenSession();
        session.BeginTransaction();
        SessionsContainer[type.ToString()] = session;

        return session;
    }

このメソッドは、新しいリポジトリが必要になるたびに呼び出され、ISession がコンストラクターに渡されます。リクエストの最後に、開いているすべてのセッションがコミットされるか、エラーが発生した場合にトランザクションがロールバックされます。

これは非常に大雑把な実装だと思いますが、うまくいくはずです。プロジェクトの最後に時間があれば、セッション管理を再検討し、できればインストーラーを実装することを目指しています。それまでの間、他にアイデアがある場合は、遠慮なく追加してください。

于 2011-06-22T13:17:11.430 に答える