ASPへのステップバイステップガイド.NETコア依存性注入


オブジェクト指向プログラミングはすべてのクラスとオブジェクトについてです、そして、複雑なソフトウェアを構築するために、我々は仕事を成し遂げるために多くのオブジェクトをつくらなければなりません.あなたがこれらのオブジェクトの作成と寿命を制御するためにどんなデザインパターンにも従わないならば、あなたはソフトウェアの小さい変化または新しい要件がアプリケーションを通してコードの多くを変えるのを強制することができる混乱に終わることができます.ソフトウェア設計パターンと原則の数は、私たちより柔軟な、管理可能な、簡単にテストソフトウェアを書くのに役立ちます.このチュートリアルでは、ASPでのファーストクラスの市民であるDependency Injectionというようなデザインパターンをカバーしようと思います.ネットコア.私はいくつかの現実世界の例の助けを借りてすべてを説明しようとするので、簡単に概念を把握することができますし、自信を持ってプロジェクトに依存性の注入を使用して起動します.
Download Source Code

依存性注入とは


ウィキペディアによると

“In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies.”

Wikipedia


私は、上記のWikipedia定義が特に理解するのが簡単でないと言わなければなりません.したがって、依存性注入に密接に関連している現実の例をあなたに与えましょう.
あなたがホテルの部屋にいて、空腹であると仮定しましょう.あなたは朝食を自分で調理を開始しますか?そうは思わない.私たちがホテルで通常行うのは、ルームサービスやホテルのレセプションを呼び出し、私たちの部屋で朝食をお送りするよう要求することです.我々は空腹であり、我々は朝食を提供するホテルのサービス/スタッフに依存しています.私たちは朝食の作り方を気にしない.我々は、誰がホテル台所で我々の朝食を作っているかさえ知りません.朝食は準備ができてホテルのルームサービス私たちの朝食を提供します.

今、プログラミングの世界に上記の現実の例をマップします.クラスAがクラスBの若干の機能性を使用するとき、クラスAはクラスBの依存性を持っていると言われます、クラスBのどんなメソッドも呼ぶために、我々はクラスAの中でクラスBのオブジェクトをつくることができて、クラスBの機能を簡単に使うことができます.いくつかの時間の後に要件を変更し、現在クラスBの機能をクラスCと呼ばれる新しいクラスと置き換える必要があるとしましょう.あなたはすぐにあなたのコードの多くの異なる場所のクラスBオブジェクトを作成し、今、どこでコードを変更する必要がありますので、大きな問題になっています.クラスを厳密に結合し、クラスBの機能をクラスCで置き換えることはできません.
依存注入は、依存関係から独立したクラスを作るプログラミングテクニックです.私たちはコードの他のクラス(依存関係)のオブジェクトを直接作成しませんが、他の誰か(DIコンテナ)に私たちのためにオブジェクトを作成するよう頼みます、そして、一旦これらのオブジェクトがつくられるならば、それらはコードでそれらを使うことができるように、私たちのクラスで提供されます(注入されます).

依存注入の利点


ここにコードに依存性注入を使用する利点がいくつかあります.

  • 柔軟で維持可能なコード:アプリケーションのコードまたはビジネスロジックを変更せずにクラスの実装を変更することができるので、コードをより柔軟でメンテナンスすることができます.コードの外部で依存関係の初期化や作成が行われるので、コードも読みやすくなります.

  • 簡単な単体テスト:我々は簡単に別の実装を1つのクラスまたは別の注入によってテストすることができます.

  • ゆるい結合:依存性注入はソフトウェア部品のゆるい結合を容易にする

  • 簡単にスケールのアプリケーション:依存性の注入は、我々はより簡単に新しいコンポーネントを導入することができないように我々のアプリケーションを拡張することが容易になりますが、我々はまた、既存のコンポーネントのより良いバージョンを実装することができますし、簡単に我々のアプリケーションに注入する.
  • 依存性注入.ネットコア


    過去に、我々はプロジェクトに依存性注入を実装するためにAutofacCastle WindsorまたはUnityのようなライブラリとフレームワークを使用していましたが、依存性注入は現在、ASPの一部です.ネットコア.構成、ロギング、ルーティングなどのすべてのフレームワークサービスは、現在ビルトインDIコンテナに登録されて、我々が彼らを必要とするところで、サービスとして我々に提供されます.基本的なアイデアは、アプリケーションが起動し、これらのサービスが注入され、実行時に解決されるすべてのサービス(依存)を登録することです.
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        { 
            services.AddTransient<IProductService, ProductService>();
            services.AddScoped<ILoggingService, LoggingService>();
            services.AddSingleton<ICacheProvider, CacheProvider>();
        }
    }
    
    ASP .NETコア依存性注入フレームワークおよびその関連クラスは、マイクロソフトで利用可能です.拡張.DependencyInjection名前空間と2つの最も重要なコンポーネントは次のとおりです.
    このインターフェイスは、依存性注入を使用する標準的な方法です.NETコアアプリケーション.我々は、このインターフェイスを使用して、我々は解決したいと私たちのアプリケーションの後に注入するすべてのサービスを登録します.Startupクラス(上記に示す)は、IServiceCollectionのインスタンスがパラメーターとして使用できるConfigureServiceメソッドを提供します.
    iErviceProvider :このインターフェイスは、実際にどのようなインターフェイスがどのような具体的な実装に属しているかを実際に調べて、サービスインスタンスを解決するために使用されます.

    ASP .ネットコアサービス


    サービス寿命は、それがゴミ集めされる前にサービスがどれくらい長く生きるかを意味します.いくつかのサービスは、短い時間のためにインスタンス化されて、特定のコンポーネントと要求だけで利用できるでしょう.一部は一度だけインスタンス化され、アプリケーション全体で利用できるようになります.ここでは、ASP . NETで利用可能なサービスのライフタイムです.ネットコア.

    シングルトン


    サービスクラスの単一のインスタンスが作成され、メモリに格納され、アプリケーション全体で再利用されます.私たちは、singleateに高価であるサービスのためにsingletonを使用することができます.また、複数のコンポーネント間で状態を共有するシナリオでも使用できます.一つの重要な点は、インスタンスが一度だけ作成され、多くの消費者がアクセスしているスレッドの安全性です.次のようにAddsingletonメソッドを使用してSingletonサービスを登録できます.
    services.AddSingleton<IProductService, ProductService>();
    

    スコープ


    サービスインスタンスはリクエストごとに1回作成されます.単一のリクエストの処理に参加するすべてのミドルウェア、MVCコントローラなどは同じインスタンスを取得します.スコープ付きサービスの良い候補は、Entity Frameworkコンテクストです.addscopedメソッドを使用してスコープサービスを登録するには、次の手順に従います.
    services.AddScoped<IProductService, ProductService>();
    

    過渡


    過渡寿命サービスは、要求されるたびに作成されます.この生涯は、ライト級、無用のサービスに最適です.これは、各消費者がサービスのコピーを取得し、スレッドの安全性が問題ではない使用するライフタイムを知らないときに良いデフォルトの選択です.AddTransactionメソッドを使用して一時的なサービスを登録できます.
    services.AddTransient<IProductService, ProductService>();
    
    あなたが上記の概念を視覚化したいならば、あなたの速い参照のためにinfographicはここにあります.

    ASP .NETコア依存性注入例


    今ではASP . NETで依存性注入を使用するいくつかの実用的な例を参照してください.ネットコア.ASPを作成します.NET Core MVC Webアプリケーションと内部モデルフォルダは、次の製品クラスを作成します.
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
    
    フォルダーサービスを作成し、単一のProductsメソッドでインターフェイスIProductServiceを追加します.
    public interface IProductService
    {
        List<Product> GetProducts();
    }
    
    次に、AmazonProductServiceという名前のクラスを作成し、このクラスのIProductServiceインターフェイスを実装します.このチュートリアルでは、データベースから製品を読み込むためのバックエンドリポジトリまたはサービスを使用していませんので、簡単にするために以下のようにgetProductsメソッドからハードコード化された製品を返します.
    public class AmazonProductService : IProductService
    {
        public List<Product> GetProducts()
        {
            return new List<Product>()
            {
                new Product() { Id = 1001, Name = "Apple AirPods Pro", Price = 249.00m },
                new Product() { Id = 1002, Name = "Sony Noise Cancelling Headphones", Price = 199.00m },
                new Product() { Id = 1003, Name = "Acer Aspire 5 Slim Laptop", Price = 346.00m } 
            };
        }
    }
    
    次に、スタートアップクラスにサービスを登録する必要があります.
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        { 
            services.AddTransient<IProductService, AmazonProductService>(); 
        }
    }
    
    次に、コントローラにサービスを注入する必要があります.以下に示すように、コントローラのコンストラクタ内でサービスを注入できます.
    public class HomeController : Controller
    {
        private readonly IProductService _productService;
        public HomeController(IProductService productService)
        {
            _productService = productService;
        }
        public IActionResult Index()
        {
            var products = _productService.GetProducts();
            return View(products);
        }
    }
    
    最後に、我々のインデックスに製品を表示することができます.以下のようにファイルを表示します
    @model List<Product>
    @{
        ViewData["Title"] = "Home Page";
    }
    <br />
    <br />
    <div>
        <h3 class="text-center">ASP.NET Core Dependency Injection</h3>
        <br />
        <table class="table">
            <thead class="thead-dark">
                <tr>
                    <th>Id</th>
                    <th>Name</th>
                    <th>Price</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var product in Model)
                {
                    <tr>
                        <td>@product.Id</td>
                        <td>@product.Name</td>
                        <td>@product.Price</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    
    アプリケーションを実行し、AmazonProductServiceから返されるすべての製品を見ることができるはずです.これは、ホームコントローラがIPrototServiceを実装するクラスのインスタンスを要求したときに、依存性インジェクションフレームワークが起動時に登録されたAmazonProductServiceに解決されたためです.CSクラス.

    あなたのアプリケーション要件が変化すると言いましょう、そして、あなたは突然、製品がアマゾンの代わりにeBayからロードされるべきであると決めました.同じIProductServiceインターフェイスを実装する別のクラスのEbayProductServiceを作成し、GetProductsメソッドの独自の実装を行うことができます.
    public class EbayProductService : IProductService
    {
        public List<Product> GetProducts()
        {
            return new List<Product>()
            {
                new Product() { Id = 2001, Name = "Apple iPhone XS Max", Price = 660.00m },
                new Product() { Id = 2002, Name = "Apple iPhone 7", Price = 134.00m },
                new Product() { Id = 2003, Name = "Sony Cyber Shot Camera", Price = 109.00m }
            };
        }
    }
    
    アプリケーションでコードの1行を変更する必要はありません.あなただけの起動時にebayproductServiceを登録する必要があります.CSファイルとあなたが完了しました.
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        { 
            services.AddTransient<IProductService, EbayProductService>(); 
        }
    }
    
    iProductServiceに依存しているコントローラとビューは、Amazon製品の代わりにeBay製品を自動的に開始します.

    DIコンテナに動的に登録する


    あなたが環境に基づいて2つの異なるサービスを使用したい状況にいるとしましょう.開発環境にいるときは、Amazonサービスをテストしますが、eBay環境を使用環境で使用します.IWebHostEnvironmentを起動クラスのコンストラクタ内に注入することで、これを簡単に実現できます.
    public class Startup
    {
        private IWebHostEnvironment _env;
    
        public Startup(IWebHostEnvironment env)
        {
            _env = env;
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
            if (_env.IsProduction())
            {
                services.AddTransient<IProductService, EbayProductService>();
            }
            else
            {
                services.AddTransient<IProductService, AmazonProductService>();
            } 
        }
    }
    

    概要


    このチュートリアルでは,依存性注入設計パターンに関連する主要概念を明らかにしようとした.私は、あなたによって提供される基盤の概要を与えました.依存性注入をサポートするNETコア.ASPを設定する方法を学びました.NETコアアプリケーションでは、組み込みのIOCコンテナを使用して登録サービスを使用します.私は、あなたが利用できる異なったサービス生涯についても学んだことを望みます.NETコアアプリケーション.