web-dev-qa-db-ja.com

Unity IoCコンテナーが使用するコンストラクターを指定する

オブジェクトの解決にUnity IoCコンテナーを使用しています。ただし、問題が発生しました。複数のコンストラクタがある場合、Unityはどのコンストラクタを使用するかをどのようにして知るのですか?パラメータありのものとなしのものがあるときに、パラメータ付きのものを使用しているようです。使用するコンストラクタを明示的に指定できますか?

具体的には、次のPersonクラスに似た2つのコンストラクターを持つケースがありました。この場合、IoCコンテナーでパラメーターなしのデフォルトコンストラクターを使用する必要がありますが、パラメーター付きのコンストラクターを選択します。

public class SomeValueObject
{
    public SomeValueObject(string name)
    {
        Name = name; 
    }
    public string Name { get; set; }
}

public class Person
{
    private string _name; 

    public Person()
    {
        _name = string.Empty;
    }

    public Person(SomeValueObject obj)
    {
        _name = obj.Name;
    }
}

これは、SomeValueObjectを作成できないため、明らかに失敗します。文字列パラメーターに何を注入するかがわかりません。それが与えるエラーは:

依存関係の解決に失敗しました。タイプ= "MyApp.Person"、名前= ""。例外メッセージ:現在のビルド操作(ビルドキーBuild Key [MyApp.Person、null])が失敗しました:コンストラクターMyApp.Person(MyApp.SomeValueObject obj)を呼び出そうとしたときに、パラメーターobjを解決できませんでした。 (戦略タイプBuildPlanStrategy、インデックス3)

コンテナー登録:

Container.RegisterType<Person, Person>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());

そして解決:

var person = Container.Resolve<Person>();
43
stiank81

代わりに次のように登録してください:

container.RegisterType<Person>(new InjectionConstructor());

RegisterTypeメソッドのオーバーロードを使用してLifetimeManagerを追加することもできます。

つまり、DIをモデリングする場合、明確なコンストラクター(つまり、オーバーロードされたコンストラクターがない場合)を使用すると、作業がはるかに簡単になります。

51
Mark Seemann

デフォルトでは、Unityは最大数の引数を持つコンストラクターを選択します。これをオーバーライドするには、必要なコンストラクタを InjectionConstructorAttribute で装飾します。

27
Anton Gogolev

属性を使用したマルチコンストラクタインジェクション

ターゲットクラスに同じ数のパラメーターを持つ複数のコンストラクターが含まれている場合、Unityコンテナーが使用するコンストラクターにInjectionConstructor属性を適用する必要がありますコンテナーが使用するコンストラクターを示します。自動コンストラクターインジェクションと同様に、コンストラクターパラメーターを具象型として指定するか、Unityコンテナーに登録済みマッピングが含まれているインターフェイスまたは基本クラスを指定できます。

4
Diadistis