web-dev-qa-db-ja.com

コンストラクターのパラメーターをUnityのResolve()メソッドに渡すことはできますか?

依存関係の注入にMicrosoftのUnityを使用していますが、次のようなことをしたいと思います。

IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context

IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);

RepositoryARepositoryBの両方にIDataContextパラメーターを受け取るコンストラクターがあり、Unityに、渡したコンテキストでリポジトリーを初期化させます。また、IDataContextはUnityに登録されていないことに注意してください(IDataContextの3つのインスタンスは必要ありません)。

85
NotDan

今日、彼らはこの機能を追加しました:

ここに最新のドロップがあります:

http://unity.codeplex.com/SourceControl/changeset/view/33899

ここでの議論:

http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434

例:

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"
70
Exist

<2セント>

後でコンテキスト以外のサービスを必要とする別のサービスを使用することにした場合はどうなりますか?

コンストラクターパラメーターとIoCの問題は、サービスインターフェイスが定義するコントラクトの一部ではなく、パラメーターが最終的に使用される具体的な型に結び付けられることです。

私の提案は、あなたもコンテキストを解決することであり、Unityには3つのインスタンスの構築を回避する方法があるべきだと思うか、オブジェクトを構築する方法があるファクトリサービスを検討する必要があります。

たとえば、従来のデータベースにまったく依存せず、代わりにXMLファイルを使用してテスト用のダミーデータを作成するリポジトリを構築することにした場合はどうでしょうか。 XMLコンテンツをコンストラクタにどのようにフィードしますか?

IoCは、コードの分離に基づいています。引数の型とセマンティクスを具体的な型に結び付けることで、実際に分離を正しく行っていないため、依存関係が残っています。

「このコードは、このインターフェイスを実装している限り、あらゆるタイプのリポジトリと通信できます。..ああ、データコンテキストを使用します」。

現在、他のIoCコンテナがこれをサポートしていることを知っています。また、私自身の最初のバージョンでもそれを使用しましたが、私の意見では、これは解決ステップに属していません。

</ 2セント>

おかげで...私は「存在」による投稿に似ています。下記参照:

        IUnityContainer container = new UnityContainer();
        container.LoadConfiguration();

        _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
        {
            new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
        });
7
Kwex

ResolvedParameter <T>( "name")内のインジェクションアーキテクチャに応じて、InjectionConstructor/InjectionProperty/InjectionMethodを使用して、コンテナに事前登録されたオブジェクトのインスタンスを取得できます。

あなたの場合、このオブジェクトは名前で登録する必要があり、同じインスタンスでは、LifeTimeManagerと同じContainerControlledLifeTimeManager()が必要です。

_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");

  var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));
5
Trecenti

非常に短い答えは:いいえ。現在、Unityには、定数または注入されていないパラメーターをコンストラクターに渡す方法がありません。私見はそれが欠けている唯一の最大のものですが、私はそれが省略ではなく設計によると思います。

ジェフ・フリッツが指摘するように、理論的には、どのコンテキストインスタンスをさまざまなタイプに注入するかを知っているカスタムライフタイムマネージャーを作成できますが、それは最初からUnityまたはDIを使用する目的を不要にするハードコーディングのレベルです。

完全なDIから少し戻って、独自のデータコンテキストの確立をリポジトリ実装に任せることができます。コンテキストinstanceはまだコンテナから解決できますが、使用するコンテナを決定するためのロジックはリポジトリの実装に入らなければなりません。確かにそれほど純粋ではありませんが、問題を取り除くでしょう。

3
Neil Hewitt

使用できる別の代替手段(良いプラクティスかどうかはよくわからない)は、2つのコンテナーを作成し、それぞれにインスタンスを登録します。

IDataContext context = _unityContainer.Resolve<IDataContext>();
_unityContainer.RegisterInstance(context);
var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context


//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance

これも役立つことを願って

1
Samuel Carrijo

NotDan、私はあなたがlassevkへのコメントであなた自身の質問に答えたかもしれないと思う。

まず、LifetimeManagerを使用して、Unityが作成するIDataContextのライフサイクルとインスタンスの数を管理します。
http://msdn.Microsoft.com/en-us/library/cc440953.aspx

ContainerControlledLifetimeManagerオブジェクトは、必要なインスタンス管理を提供するようです。そのLifetimeManagerを適切に配置すると、UnityはIDataContextの同じインスタンスをIDataContext依存関係を必要とするすべてのオブジェクトに追加する必要があります。

0
Jeff Fritz