Dependency Injectionとは
Dependency Injection(以降DI)は、直訳すると依存関係の注入です。なんの依存関係かというと、クラス間の依存関係です。例えば、車クラスがあったとして、車クラスはエンジンクラスの性能により、燃費が決まります。この時、車クラスはエンジンクラスに依存しています。ちなみに、MSDNでは、以下のように記述されています。
ASP.NET Coreは、dependency injection(DI) ソフトウェアデザインパターンに則っています。DIは、クラスとその依存性のInversion of Control (IoC)を達成するための技術です。 .NETにおけるDIは、configurationやlogging、そしてoptionパターンとともにフレームワークに組み込まれています。
Inversion of Control*参考文献2
Inversion of Controlのリンクに開くと、Dependency Inversionに関する記事が表示されます。この2つの関係性はよくわかりませんが、Dependency Inversionについて調査しました。MSDNのArchitectual principleでは、以下のような記載があります。
アプリケーションにおける依存の方向は、実装の詳細ではなく、抽象化であるべきだ。
どういうことか、車クラスを例に示します。車クラスには、エンジンクラスが必要であり、エンジンクラスにはガソリンクラスが必要だとします。この場合、ほとんどのアプリケーションでは、車クラスはエンジンクラスを参照し、エンジンクラスはガソリンクラスを参照します(下図左)。しかし、Dependency Inversionに則ったアプリケーションでは、間にインターフェースを挟みます。そのため、車クラスはエンジンインターフェースを参照し、エンジンクラスはエンジンインターフェースを実装します。エンジンクラス、ガソリンインターフェース、ガソリンクラスでも同様の関係となります(下図右)。
MSDNでは、Dependency Inversionに則る利点について、以下のように記しています。
Dependency inversionは、依存関係の弱いアプリケーションを開発するための重要な要素です。なぜなら、実装の詳細を、より高い抽象化に依存して書くことができるためです。その結果、アプリケーションはよりテスト・モジュール化・メンテナンスがしやすくなります。
Dependency Inversionに則ることによって、クラス間の依存がインターフェースを介したものになり、その結果、アプリケーションのテスト・モジュール化・メンテナンスが容易になる、ようです。
そう考えると、ここでやっているのは、オブジェクト指向プログラミングの特徴の1つである、抽象化であると僕は考えています。抽象化とは、「詳細なオブジェクトではなく、単純なオブジェクトを用いること」*参考文献3*参考文献4で、今回の例では、車クラスからエンジンクラスを参照する必要はなく、その実装元であるエンジンインターフェースで十分なため、インターフェースを参照している点が、まさに抽象化であると考えております。
Program.csで行われていること
Program.cs中のDIに関する処理の概要
DIとは何かがわかると、Program.csで行われていることが少しわかるようになります。Program.csには、WebアプリをBuildするための処理が書かれており、その処理の一部がDIになります。DIに関する処理を説明する前に、これから登場する語句について、一度説明します。
登場する語句
Service
DIにおけるServiceについて、MSDNでは、以下のように説明されています。
- 他のオブジェクトにサービスを提供するオブジェクト
- web serviceを使用することもあるが、web serviceとは関係ない
上記の説明ではよくわかりませんが、僕は他のクラスに参照されているクラス、というように認識しております。
WebApplicationBuilder
WebApplicationとserviceのためのBuilder。
WebApplication
Httpパイプラインとルートを設定するために使用されるWebApplication。
ServiceDescripter
Service自身の型、Interface、ライフタイムを明記する。
IServiceCollection
ServiceDescripterのCollectionのための契約を明記する。英語を直訳したのですが、これもわかりづらい。
ServiceDescripterを保有しているコレクション、だと認識しています。
IServiceProvider
Service Objectを取得するためのメカニズムを定義する
Program.cs中のDIに関する処理
上記で説明したように、依存関係を挿入するためには、ServiceとそのServiceが実装しているInterfaceの情報が必要となります。Program.csでは、WebApplicationBuilderクラスのIServiceCollectionプロパティにそれらの情報(Service Descriptor)を挿入します。例えば、以下のコードでは、WebApplicationBuilderクラスをインスタンス化し、そのIServiceCollectionにControllerに関するServiceを登録しています。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
そして、必要なService DescriptorをIServiceCollectionに追加すると、WebApplicationBuilder.Build()によって、WebApplicationインスタンスを生成します。WebApplicationインスタンスには、IServiceProviderプロパティが含まれており、これを用いて登録されたServiceを取得することができます。
まとめ
- Dependency Injectionとは、クラス間の依存関係を弱めるために用いられるソフトウェアデザインパターンです。
- Dependency Injectionでは、クラスではなく、そのInterfaceを参照することによって、依存関係を弱めます。
- ASP.NET Core MVCでは、参照されるクラスのことをServiceと呼び、ServiceDescriptorをServiceCollectionに挿入、そして、IServiceProviderで情報を取得します。
引用文献
- MSDN, “.NET dependency injection“, 最終更新日 : 2024/03/15
- MSDN, “Architectural principles“, 最終更新日 : 2023/09/05
- MSDN, “WebApplicationBuilder Class“, 最終閲覧日 : 2024/04/07
- MSDN, “WebApplication“, 最終閲覧日 : 2024/04/07
- MSDN, “ServiceDescriptor“, 最終閲覧日 : 2024/04/07
- MSDN, “IServiceCollection“, 最終閲覧日 : 2024/04/07
- MSDN, “IServiceProvider“, 最終閲覧日 : 2024/04/07
参考文献
- MSDN, “Dependency Injection in ASP.NET Core“, 最終更新日 : 2023/11/07
- MSDN, “Architectural principles“, 最終更新日 : 2023/09/05
- DigitalOcean, “What is Abstraction in OOPS?“, 最終更新日 : 2022/08/04
- TechMania, “オブジェクト指向とは?具体例を交えてわかりやすく解説”, 最終更新日 : 2024/01/23
- MSDN, “MvcServiceCollectionExtensions.AddControllersWithViews Method“, 閲覧日 : 2024/04/07
コメント