2011-01-10 6 views
2

Microsoft Unity IoCで、Resolve<SomeType>()を呼び出した場合、返されるオブジェクトが現在のセッションで作成されたものであることを保証できますか?Resolve <T>()はセッションごとにオブジェクトを返しますか?

たとえば、3人のユーザーがサインオンし、コンテナ内に作成されるSomeTypeのオブジェクトには、各ユーザーごとに異なる値が設定されているとします。 Resolveへの呼び出しは、現在のユーザー用に作成されたオブジェクトを返しますか?または、それは作成された最後のものを返すような何か愚かなことをするだろうか?

私はいくつかの環境問題のために自分自身をテストするのにトラブルがあり、すぐに何かをチェックする必要があるので、誰かがこれに答えることができれば非常に役に立ちます!

編集

私はUnityに非常に新しいですが、私は一意の名前で、コンテナ内のオブジェクトを登録し、その名前によってそれらを取得することができるはずのようwhat I read hereに基づいて、それはそうするために私を許して。だから、私は、セッションIDまたは私のオブジェクトを取得するセッション内に持続する他の値を使用することができないだろうか?

+0

「キー」に対してインスタンスを登録している場合は、Unityをキャッシュとして使用したいと思うようです。これは本当にユニティが\のベストなものではなく、あなたが得ている答えが混乱しているのかもしれません。 –

+1

Unityをキャッシュとして使用すると、Webファームを持っているときに何が起こるのですか、ASP.Netワーカープロセスがリサイクルするときに何が起こりますか? –

+0

@chibacityが言ったことに加えて、別のスレッド間でインスタンスを共有している場合、あなたは傷つく世界のために自分自身を開いています。特定の要求にどのスレッドが対応しているかは完全に非決定的なので、アクセスしたいときは左と中央を同期させる必要があります。本当に、新しいオブジェクトを作成する、それがDBへの旅行を必要とするならevernはそれほど高価ではありません。 –

答えて

6

AM MVCアプリでUnityを使用しています。どこから始めますか?

まず、同じセッションで要求間で同じインスタンスが使用されることを保証するASP.NETシステムがないため、セッションシングルトンは実際には不可能です。セッションは、リクエスト間でシリアライズおよびデシリアライズすることで、セッション内で永続化された同じオブジェクトを模倣することができます。

一時インスタンス - つまり、生涯管理仕様のない単純な登録は、99%の時間で十分です。これは、登録された型のインスタンスが必要なたびに作成されることを意味します。

ごくまれに、要求の存続期間中存続するインスタンスが必要です。しかし、あなたがそれらを必要とするときは、本当にそれらが必要です。 DBへの接続はこれのための完全な候補です。一方、リクエストシングルトンは、作成と管理がずっと簡単です。

最も洗練された解決策は、Unityの子コンテナ機能を使用することです。リクエストの最後に配置された子コンテナをリクエストの最初に作成することができます(追加のボーナスとしてContainerControlledLifetimeManagerのインスタンスをすべて破棄します)。

子コンテナを作成する場合、親コンテナからすべての登録が引き続き使用できるため、リクエスト固有のものを子コンテナに登録する必要があります。ここで

この作業を取得するための擬似コードです:実行する必要がある

private void Application_Start() { 
    _parentContainer = new UnityContainer(); 
    //creates a transient registration, available at any point in the app. 
    _parentContainer.RegisterType<IParentIntf, ParentIntfImpl>(); 
    ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory()); 
} 

private void Application_BeginRequest() { 
    var childContainer = _parentContainer.CreateChildContainer(); 
    //registers a request "singleton" 
    //This registration is a type registration, an instance of RequestInterfaceImpl 
    //will be created when needed and then kept in the container for later use. 
    childContainer.RegisterType<IRequestInterface,RequestInterfaceImpl>(new ContainerControlledLifetimeManager()); 
    //save the child container in the context, so we can use it later 
    HttpContext.Items["childContainer"] = childContainer; 
} 

private void Application_EndRequest() { 
    //dispose the child container 
    ((IUnityContainer)HttpContext.Items["childContainer"]).Dispose(); 
} 

もうひとつは、コントローラを作成するために、子コンテナを使用するようにコントローラの工場をオーバーライドすることです。コントローラは、アプリケーションへの最初のエントリポイントであり、コンストラクタ内の他のコンポーネントに依存することができます。

public class UnityControllerFactory : DefaultControllerFactory { 

    #region IControllerFactory Members 

    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) { 
     IController controller; 
     controllerName = controllerName.ToLower(); 
     var container = ((IUnityContainer)HttpContext.Items["childContainer"]) 
     if(container.IsRegistered<IController>(controllerName)) 
      controller = container.Resolve<IController>(controllerName); 
     else 
      controller = base.CreateController(requestContext, controllerName) ; 
     return controller; 
    } 
} 
+0

OPは、リクエストスコープではなく、セッションスコープを希望することを示します。しかし、私は(最後のコメントで述べたように)、要求範囲を考慮する必要があることに同意します。 –

+0

はい、私はそれを実現しました。 –

+1

ASP.NETでのセッション変数のシリアライゼーションの問題を説明するための太った+1。これは、多くの開発者がアプリケーションを複数のサーバーにスケールアウトし、アウトプロセスセッションストアを使用しなければならないまで実現しないものです。それから、あなたはうんざりです。 – Steven

2

デフォルトの動作では、各解決呼び出しごとに新しいインスタンスが返されますが、これは必要なものではありません。

セッション内で同じインスタンスを作成して解決することは可能ですが、私が知る限りサポートは組み込まれていません。あなたはあなた自身の生涯マネージャーを書く必要があり、あなたのタイプを登録するときこれを使用しなければなりません。

スレッドインスタンスごとに行うことができるライフタイムマネージャがありますが、これはスレッドが再利用されるためセッションには役立ちません。また、解決は本当にセッションスコープであるために複数の要求を処理する必要があります。

誰かがこのために生涯のマネージャーを書いたことは完全に可能です。

+0

@Samoどのようにオブジェクトを登録していますか、生涯マネージャは何を使用していますか? RegisterInstanceを使用する場合、もちろん同じインスタンスが返されます。 –

+0

私は以前のコメント(何らかの初期化が行われていた)と誤解されたので、削除しました。異なる製品が同じコードを使用し、コンテナに異なるクラスを登録するため、私はRegisterTypeを使用しています。私のニーズの両方に対応するアプローチはありますか? LifetimeManagerはContainerControlledLifetimeManagerです – Samo

+0

@Samoセッションスコープのインスタンスを提供するものは何もありません(ASP.Netセッション状態管理と統合する必要があります。これはメモリ内またはSQL Serverなどです)。これはUnityが独自にやっていないことです)。 'ContainerControlledLifetimeManager'は実際にあなたにシングルトーン、つまり' Resolve'のすべての呼び出し元が共有する単一のインスタンスを与えます。あなたのコンテナをどのように管理していますか?それは静的ですか? –

関連する問題