現時点では、このトピックでかなり多くのことがすでに述べられており、Habréを含めて書かれていますが、豊富な情報のために、本当に有用なコンテンツを見つけることは困難です。 さらに、これらの概念はしばしば混乱したり、混乱したりします。 多くの資料を分析したので、私はこの主題に対する私のビジョンを提示することにしました。
理論
私にとって、IoCとDIの関係は、アジャイルとスクラムの関係と同じです。
Inversion of Controlは抽象的な原理であり、疎結合コードを記述するための一連の推奨事項です。 その本質は、他のコンポーネントの特定の実装の詳細に依存することなく、システムの各コンポーネントを可能な限り他のコンポーネントから分離する必要があるということです。
依存性注入(依存性注入)は、この原則の実装の1つです(これに加えて、 ファクトリメソッド 、 サービスロケーターもあります )。
IoCコンテナーは、必要に応じて何らかの種類のライブラリ、フレームワーク、プログラムです。これにより、このアプローチを使用してコードの記述をできるだけ簡素化および自動化できます。 それらの多くは、あなたに都合の良いものを使用して、私はNinjectの例ですべてを実証します。
練習する
管理反転アプローチによれば、特定のサービスを使用するクライアントがいる場合、彼はこれを直接ではなく、仲介業者、一種のアウトソーシングを通じて行う必要があります。
これがどの程度技術的に行われ、IoCアプローチの各実装を定義します。
簡単な例を使用して、DIを使用します。
スケジュールを作成するクラスがあり、別のクラスがそれを表示するとします(通常は、デスクトップアプリケーション用、Web用などなど、多くのクラスがあります)。
IoC、DIについて何も知らなかった場合、次のように記述します。
class ScheduleManager { public Schedule GetSchedule() { // Do Something by init schedule... } } class ScheduleViewer { private ScheduleManager _scheduleManager = new ScheduleManager(); public void RenderSchedule() { _scheduleManager.GetSchedule(); // Do Something by render schedule... } }
すべてがうまくいくように見えますが、コードはタスクを解決しますが、後でスケジュールマネージャーの実装を変更したり、そのようなマネージャーをいくつか持ち、それらを動的に置き換える場合はどうでしょう。 その後、ScheduleViewerで何かを変更する必要があるため、再度テストする必要があります。
幸いなことに、開発者、言葉の意味で怠け者、そして同じことを二度行うのは好きではありません。
たとえば、 依存関係注入(DI)を使用してこのスチールスレッドのもつれを解消します。IScheduleManagerインターフェイスの形式でレイヤーを追加することにより、これらのクラス間の関係を弱めます。 そして、DIテクニックのメソッドの1つであるコンストラクターインジェクション (さらに、 セッターインジェクションとメソッドインジェクションがあります -簡単に言えば、インターフェイスは特定のクラスの代わりに、たとえばプロパティタイプやメソッド引数タイプにあります):
interface IScheduleManager { Schedule GetSchedule(); } class ScheduleManager : IScheduleManager { public Schedule GetSchedule() { // Do Something by init schedule... } } class ScheduleViewer { private IScheduleManager _scheduleManager; public ScheduleViewer(IScheduleManager scheduleManager) { _scheduleManager = scheduleManager; } public void RenderSchedule() { _scheduleManager.GetSchedule(); // Do Something by render schedule... } }
次に、クラスを使用してスケジュールを表示する場所に次のように記述します。
ScheduleViewer scheduleViewer = new ScheduleViewer(new ScheduleManager());
今ではほぼ完璧ですが、ScheduleManagerを常に使用するプロジェクトの周りにさまざまなScheduleViewerが散在している場合(毎回手で作成する必要があります)および/または何らかの方法で動作をカスタマイズして、1つの状況でどこでも使用する場合ScheduleManager、および別の例ではAnotherScheduleManagerなど
IoCコンテナーは、この問題を解決するように設計されています。
IoCコンテナー
これらはルーチンの量を減らすのに役立ち、インターフェースとその特定の実装との対応を設定できるため、後でどこでも使用できます。
上で言ったように、Ninjectの例でこれを検討します-
1.最初に、コンテナ構成を作成します。
class SimpleConfigModule : NinjectModule { public override void Load() { Bind<IScheduleManager>().To<ScheduleManager>(); // , : // .. Bind<ScheduleViewer>().ToSelf(); } }
これで、必要なIScheduleManagerがScheduleManagerに置き換えられます。
2.コンテナー自体を作成し、そのコンフィギュレーターを示します。
IKernel ninjectKernel = new StandardKernel(new SimpleConfigModule()); // ScheduleViewer new, : ScheduleViewer scheduleViewer= ninjectKernel.Get<ScheduleViewer>();
コンテナ自体がScheduleManagerクラスのインスタンスを作成し、ScheduleViewerコンストラクターを呼び出し、新しく作成されたScheduleManagerのインスタンスをそれに代入します。
おわりに
そして最後に、IoC、DIは非常に優れたツールですが、他のメカニズムと同様に、意識的かつ場違いに使用する必要があります。 たとえば、何かが変更される可能性が低い小さなコンソールアプリケーション、または顧客の要望がしばしば可変的で矛盾している大規模なプロジェクトです。
それだけです、私はあなたのコメント、建設的なコメントを聞いてとてもうれしいです。
制作中の皆さんに幸運を。