web-dev-qa-db-ja.com

ファクトリー/ DIを組み合わせることはできません

Fooクラスがあり、2つの依存関係があると仮定してください:ISerializer<T>IFileAccessHandler

現在、このクラスには他の依存関係、機能依存関係もあります。このクラスを無効な状態でインスタンス化したくないので、コンストラクターでドメインオブジェクトを渡す必要もあります。

しかし、実際にクラスFooを作成しているときに渡すドメインオブジェクトもわかっている場合、IoCでそれをどのように処理できますか?

ドメインオブジェクトを、ファクトリで設定したプロパティにしました。したがって、ファクトリはService Locatorを呼び出して、適切にインスタンス化された「Foo」クラスをその依存関係で取得し、さらに正しいドメインオブジェクトで埋めて返します。

しかし、これは最善の方法ですか?私は、実際に "Foo"で作業する必要があると思わせるために、コンストラクターのドメインオブジェクト部分を含めることをお勧めします。

何か案は?ここで何か不足していますか?

45
Laila

登録時に具象型を接続できない場合のDIのデフォルトの解決策は、Abstract Factoryを使用することです。

あなたの場合、IFooFactoryインターフェイスを定義します。

public interface IFooFactory
{
    Foo Create(DomainClass dc);
}

これにより、インフラストラクチャサービスを認識する具体的な実装を定義できます。

public class FooFactory : IFooFactory
{
    private readonly ISerializer serializer;
    private readonly IFileAccessHandler fileHandler;

    public FooFactory(ISerializer serializer, IFileAccessHandler fileHandler)
    {
        if(serializer == null)
        {
            throw new ArgumentNullException("serializer");
        }
        if(fileHandler == null)
        {
            throw new ArgumentNullException("fileHandler");
        }

        this.serializer = serializer;
        this.fileHandler = fileHandler;
    }

    public Foo Create(DomainClass dc)
    {
        return new Foo(this.serializer, this.fileHandler, dc);
    }
}

このようにして、Fooクラスの不変条件を保護するを使用して、コンストラクタインジェクションを維持できます。

DIコンテナーでは、IFooFactoryと対応する実装を登録できます。 DomainClassインスタンスがあり、Fooインスタンスが必要なすべての場所で、IFooFactoryへの依存関係を取得して使用します。

71
Mark Seemann

私もこの問題に取り組んでいます。 Markの例は、FooFactoryが具象クラスFooを作成するという制約があります。起動構成中に実装が決定されるIFooを作成する場合はどうなりますか?これは、IFooのすべての代替実装(FooA、FooBなど)について、対応するファクトリ(FooAFactory、FooBFactoryなど)の具体的な実装が必要であることを意味します。これは冗長だと思います。

ファクトリがコンテナの実装と初期化と同じレベルで定義されている場合、ファクトリがコンテナを参照することの弱点はわかりません。それでも、コンテナーの参照がアプリ​​ケーションの残りの部分に漏れないようにします。

宜しくお願いします、

メトロ。

0
Metro