24

次のコードがある場合:

public class RobotNavigationService : IRobotNavigationService {
  public RobotNavigationService(IRobotFactory robotFactory) {
    //...
  }
}
public class RobotFactory : IRobotFactory {
  public IRobot Create(string nameOfRobot) {
    if (name == "Maximilian") {
      return new KillerRobot(); 
    } else {
      return new StandardRobot();
    }
  }
}

私の質問は、ここで制御の反転を行う適切な方法は何ですか? KillerRobot と StandardRobot の具象を Factory クラスに追加したくありませんか? IoC.Get<> でそれらを取り込みたくありませんよね?bc は Service Location であり、真の IoC ではありませんか? 実行時にコンクリートを切り替える問題にアプローチするより良い方法はありますか?

4

4 に答える 4

36

あなたのサンプルでは、​​完全に優れたファクトリ実装があり、私は何も変更しません。

ただし、KillerRobot および StandardRobot クラスには、実際には独自の依存関係があると思われます。IoC コンテナーを RobotFactory に公開したくないことに同意します。

1 つのオプションは、ninject ファクトリ拡張を使用することです。

https://github.com/ninject/ninject.extensions.factory/wiki

ファクトリを注入する方法は 2 つあります。インターフェイスを使用する方法と、IRobot (またはその他のもの) を返す Func を注入する方法です。

インターフェイス ベースのファクトリ作成のサンプル: https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface

func ベースのサンプル: https://github.com/ninject/ninject.extensions.factory/wiki/Func

必要に応じて、IoC 初期化コードで func をバインドして実行することもできます。何かのようなもの:

var factoryMethod = new Func<string, IRobot>(nameOfRobot =>
                        {
                            if (nameOfRobot == "Maximilian")
                            {
                                return _ninjectKernel.Get<KillerRobot>();
                            }
                            else
                            {
                                return _ninjectKernel.Get<StandardRobot>();
                            }

                        });
_ninjectKernel.Bind<Func<string, IRobot>>().ToConstant(factoryMethod);

ナビゲーション サービスは次のようになります。

    public class RobotNavigationService
    {
        public RobotNavigationService(Func<string, IRobot> robotFactory)
        {
            var killer = robotFactory("Maximilian");
            var standard = robotFactory("");
        }
    }

もちろん、このアプローチの問題は、IoC 初期化内にファクトリ メソッドを記述していることです。おそらく最良のトレードオフではありません...

factory 拡張機能は、いくつかの規則ベースのアプローチを提供することでこれを解決しようとします。したがって、コンテキスト依存の依存関係を追加して、通常の DI チェーンを維持できます。

于 2012-04-23T18:32:25.177 に答える
3

KillerRobot と StandardRobot の具象を Factory クラスに追加したくありませんか?

おそらくそうすることをお勧めします。具体的なオブジェクトをインスタンス化しない場合、ファクトリの目的は何でしょうか? 私はあなたがどこから来ているかを見ることができると思います-IRobot契約を説明している場合、注射コンテナはそれを作成する責任があるべきではありませんか? それがコンテナの目的ではありませんか?

多分。ただし、オブジェクトを処理する具体的なファクトリを返すnewことは、IoC の世界ではかなり標準的なパターンのようです。コンクリート工場に実際の仕事をさせることは原則に反するとは思いません。

于 2012-04-23T18:33:24.490 に答える