したがって、私が読んだことからそれを行う理想的な方法は、IOCにアクセスする必要があるときはいつでもカーネルを注入することです...まあ、それで問題ありません。SLの使用は最小限に抑えています。
いいえ、カーネルをビジネス クラスに注入することは最善の方法ではありません。より良い方法は、たとえばファクトリを作成するIFooFactory { IFoo Create(); }
かFunc<IFoo>
、これに新しいインスタンスを作成させることです。
このインターフェースの実装は複合ルートに入り、カーネルのインスタンスを取得し、カーネルを使用して解決を行います。これにより、クラスが特定のコンテナーから解放され、別のコンテナーを使用して別のプロジェクトでそれらを再利用できます。Func の場合、次のモジュールを使用できます。Ninject は Func (自動生成されたファクトリ) をサポートしていますか? Ninject 2.4 では、これがネイティブでサポートされます。
リファクタリングに関する限り、アプリケーションのソース コードを知らずに何が最善の方法であるかを伝えることはほとんど不可能です。おそらく機能するアプローチを提供できます。
長期的には、アプリケーション全体を適切な DI にリファクタリングする必要があると思います。非常に大規模なプロジェクト (30 ~ 40 人年) で私がかつて行ったことは、次のようなものでした。
複合ルートから開始し、オブジェクト ツリーをたどり、適切な DI を使用するようにクラスを次々と変更します。すべてのリーフに到達したら、他のサービスに依存しないすべてのサービスのリファクタリングを開始し、同じアプローチを使用してそれらのリーフで動作します。その後、既にリファクタリングされたサービスのみに依存するサービスを続行し、すべてのサービスがリファクタリングされるまで繰り返します。これらのすべてのステップを順番に実行できるため、コードが継続的に改善され、同時に新しい機能を追加することもできます。それまでの間、ServiceLocation は、できるだけ早く正しくすることに重点が置かれている限り、許容されます。
疑似コードの例:
Foo{ ServiceLocator.Get<Service1>(), new Bar() }
Bar{ ServiceLocator.Get<IService1>(), ServiceLocator.Get<IService2>(), new Baz() }
Baz{ ServiceLocator.Get<IService3>() }
Service1 { ServiceLocator.Get<Service3>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { new SomeClass()}
ステップ 1 - ルート (Foo) を変更する
Foo{ ctor(IService1, IBar) }
Bar{ ServiceLocator.Get<IService1>(), ServiceLocator.Get<IService2>(), new Baz() }
Baz{ ServiceLocator.Get<IService3>() }
Service1 { ServiceLocator.Get<IService2>() }
Service2 { ServiceLocator.Get<IService3>() }
Service3 { new SomeClass()}
Bind<IBar>().To<Bar>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
ステップ 2 - ルートの依存関係を変更する
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ServiceLocator.Get<IService3>() }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { new SomeClass()}
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().ToMethod(ctx => ServiceLocator.Get<IService2>());
ステップ 3 - 依存関係を変更し、リーフになるまで続行します
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { new SomeClass() }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().ToMethod(ctx => ServiceLocator.Get<IService2>());
Bind<IService3>().ToMethod(ctx => ServiceLocator.Get<IService3>());
ステップ 4 - 他のサービスに依存しないサービスをリファクタリングする
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ServiceLocator.Get<Service3>() }
Service3 { ctor(ISomeClass) }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<ISomeClass>().To<SomeClass>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().ToMethod(ctx => ServiceLocator.Get<IService2>());
Bind<IService3>().To<Service3>().InSingletonScope();
ステップ 5 - 次に、依存関係としてサービスをリファクタリングしただけのサービスに依存するものをリファクタリングします。
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ServiceLocator.Get<Service2>() }
Service2 { ctor(IService3) }
Service3 { ctor(ISomeClass) }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<ISomeClass>().To<SomeClass>();
Bind<IService1>().ToMethod(ctx => ServiceLocator.Get<IService1>());
Bind<IService2>().To<Service2>().InSingletonScope();
Bind<IService3>().To<Service3>().InSingletonScope();
ステップ 6 - すべてのサービスがリファクタリングされるまで繰り返します。
Foo{ ctor(IService1, IBar) }
Bar{ ctor(IService1, IService2, IBaz) }
Baz{ ctor(IService3) }
Service1 { ctor(IService2) }
Service2 { ctor(IService3) }
Service3 { ctor(ISomeClass) }
Bind<IBar>().To<Bar>();
Bind<IBaz>().To<Baz>();
Bind<ISomeClass>().To<SomeClass>();
Bind<IService1>().To<Service1>().InSingletonScope();
Bind<IService2>().To<Service2>().InSingletonScope();
Bind<IService3>().To<Service3>().InSingletonScope();
おそらく、リファクタリングと一緒に規約ベースのコンテナー構成に切り替えたいと思うでしょう。この場合、リファクタリングされたすべてのクラスに属性を追加してそれらをマークし、すべてのリファクタリングが完了した後に再度削除します。規則では、この属性を使用して、リファクタリングされたすべてのクラスをフィルタリングできます。