Service Locatorフレームワークが依存性注入コンテナと呼ばれることが多いのはなぜですか?
まず、これら2つの概念を理解する方法は次のとおりです。サービスロケーターは依存性注入ではありません。ServiceLocatorとDependencyInjectionはどちらも、制御の反転のアプリケーションです。これは、このトピックに関するMartinFowlerの記事を読んだ後に私が到達した理解です。私の理解が間違っている場合は、その方法を説明してください。
オンラインの多くの場所で、依存性注入ライブラリまたはフレームワークと呼ばれるサービスロケーターと呼ばれるものを見てきました。たとえば、Simple Injectorは、それ自体を「.NET用のオープンソースの依存性注入(DI)ライブラリ」と呼んでいます。ただし、クイックスタートページには、SimpleInjectorがサービスロケーターであることを明確に示す例が示されています。Microsoftは、.NET Core名前空間「Microsoft.Extensions.DependencyInjection」を提供しています。これは、明らかにサービスロケーターでもあります。2016年のEssential.NETブログ投稿「.NETCoreによる依存性注入」では、「。NET CoreDIフレームワーク」を使用してサービスを登録する方法について詳しく説明しています。
もちろん、実際に自動化された依存性注入を実行するNinjectなど、真の(私が理解しているように)依存性注入コンテナがあります。
これらの概念の違いを誤解していますか?そうでなければ、どうしてそんなに徹底的に混同されるようになったのでしょうか?
回答
「依存性注入」フレームワークであろうと「サービスロケーター」フレームワークであろうと、サービスの知識をフレームワークに取り込む必要があります。
framework.register(abstractType, concreteType)
使用しているフレームワークに関係なく。違いは、フレームワークから物事を再び取り出す方法にあります。
- サービスロケーターを使用すると、サービスのインスタンスが必要になるたびに、を呼び出します
framework.get(abstractType)
。 - 依存性注入を使用すると、依存関係をあるレイヤーから次のレイヤーに受け渡し、フレームワークにそれらの依存関係を結び付ける仕事をさせます。(
framework.get
トップレベルで数回の呼び出しが必要になる場合がありますが、サービスが必要になるたびに呼び出す必要はありません)。
確かに後者はMicrosoft.Services.DependencyInjection
使用目的であり、NInjectの使用方法と実際には何の違いもありません。
最初の違いは次のとおりです。すべてのサービスロケーターが依存性注入コンテナーであるとは限りません。サービスロケーターは、依存性注入以外の目的で使用できます。これにより、隠れた依存関係(SLとDIに関するFowlerの説明を参照)などの問題が発生し、SLがアンチパターンであると見なされる場合もあります(ただし、最終的にどのように使用されるかによって異なります)。
2つ目の、さらに重要な違いは、依存性注入コンテナーは単なるサービスロケーターではなく、サービスコンポーザーでもあるということです。
たとえば、参照したSimpleInjectorの例では、コンテナーがサービスをインスタンス化する方法(シングルトンとファクトリ)についても通知され、コンテナー自体がサービスを構成し、CancelOrderService
既知の依存関係を自動的に解決して注入することがわかります。コンテナで設定された依存関係マップのヘルプ。そして、この最後の機能は、依存関係に依存するオブジェクトをインスタンス化するたびに、退屈で退屈な定型コードをたくさん書く必要がないDIフレームワークの真の利点です。
サービスの場所と依存性の注入
サービスロケーターは依存性注入ではありません。
私は同意しませんが、あなたは私が同意していないこととは異なる何かを言う/焦点を合わせるつもりだと思います。
まず第一に、Philip Kendallの答えは、抽象から具体へのタイプの登録はどちらの場合も同じであるという正解です。唯一の本当の違いは、それらの登録にアクセスする方法です。
内部的には、DIフレームワークはサービスロケーターを使用して注入可能なインスタンス/タイプを検索します。本質的に、サービスロケーターは、登録された抽象から具象型の登録を含む辞書です。論理的には、DIフレームワークは、これらの登録を追跡して、必要なときにそれらを取得できるようにする必要があります。
Service Locatorフレームワークが依存性注入コンテナと呼ばれることが多いのはなぜですか?
依存性注入と呼ばれるものは、実際には単なるサービスの場所ですが、開発者(=フレームワークのユーザー)を強制する代わりに、コンストラクター署名1に基づいてサービスを自動的に検索し、登録されているすべてのタイプのファクトリとして機能する機能が追加されていますフレームワークのサービスロケーターからサービスを直接要求し、依存性グラフを手動で作成する必要があります。
注:開発者がコンストラクター本体内でサービスを検索するか、サービスを検索した後にコンストラクターを手動で呼び出すかは、ここでは関係ありません。いずれの場合も、依存するクラスにサービスを提供することにより、依存グラフを手動で作成する必要がありました。
したがって、あなたの質問に対する簡単な答えは、「DIフレームワークは本質的に、登録されたサービスの場所を抽象化するいくつかの追加機能を備えたサービスロケーターであるため」です。
警告
1コメントで異議が唱えられたため、サービスロケーターなしでDIを実行できることに同意しますが、そうする単一のDIフレームワークにまだ遭遇していません。SLなしでフレームワークとしてDIを実行すると、開発者に多大な労力がかかるため、フレームワークはもはや意味のある価値を実際に追加しなくなると思います。
DIフレームワークでSLを使用しないDIの例を見てみたいと思います。
この質問はDIフレームワークと私たちがそれらと呼ぶものに焦点を当てているので; 私は、質問が定義する文脈の中で私の主張を支持します。