1. ホーム
  2. Web プログラミング
  3. ASP.NET

ASP.NET Core ディペンデンシーインジェクションの詳細

2022-01-14 17:16:56

前文です。

ASP.NET Core アプリケーションは起動時に様々なコンポーネントに依存してサービスを提供しますが、これらのコンポーネントはインターフェースという形で標準化されており、これがサービスと呼ばれるものです。 ASP.NET Core フレームワークは、必要なサービスを提供するためにコンテナを使用する、依存性注入フレームワークの上に構築されています。依存性注入コンテナとそのメカニズムを理解するために、依存性注入とは何かを理解する必要があります。

I. コントロールインバーシオン

依存性注入について語るとき、制御の逆転(IoC)について言及することは重要である。
/
定義する。 高レベルのモジュールは低レベルのモジュールに依存してはいけません。どちらもその抽象的なものに依存すべきです。
抽象化されたものは、細部のばらつきに比べ、はるかに安定しています。抽象化に基づいて構築されたアーキテクチャは、細部に基づいて構築されたアーキテクチャよりもはるかに安定しています。つまり NET インターフェースや抽象クラスを使う目的は、具体的な操作に立ち入らずに、優れた仕様や契約を設定し、その詳細を実装クラスに提示することにあります。

II. ハリウッド・ルール

私たちを呼ばないで、私たちがあなたを呼びます。 don't call us, we'll call you ハリウッドの有名な原則です。ハリウッドでは、俳優事務所に履歴書を提出したら、あとは家に帰って待つだけです。ハリウッドでは、履歴書を提出したら、あとは家で待っていればいいのです。 IIOC この原則は、ハリウッドの原則である「すべての構成要素は受動的である」( Passive ) であり、コンポーネントの初期化および起動はすべてコンテナによって処理される。
ASP.NET MVC の開発では、合意されたルール (定義されたディレクトリや命名規則) に従って、対応する controller View ファイルを作成します。フレームワーク全体は、ルーティングルールによって解決されたパラメータを、ターゲットの Controller で、もしターゲットの Action メソッドをレンダリングする必要があります。 View で、フレームワークは対応する View ファイル( .cshtml ファイル) を動的にコンパイルして、クライアントへの html レスポンスを生成していますが、フレームワーク全体では、このような IoC という考え方があります。

III. プロセス制御

IoC は、プロセスの制御をアプリケーションからフレームワークに移行し、エンジンでプロセスの自動実行を駆動するものです。アプリケーションは、ワークフローの詳細を気にする必要はなく、エンジンを起動するだけでよいのです。フレームワークはスタンドインという形で拡張ポイントを提供し、アプリケーションは拡張ポイントを登録することでプロセスの一部を制御することができる。エンジン(コンテナ)が起動されると、登録された拡張機能は自動的にプロセス全体の実行に関与するようになる。

この上の図でIoCの役割を見るとわかりやすいですね。
使用する前に プログラム全体がお互いに依存しあっていて、新しい要件が挙がると、あることが別のことにつながってしまう、これは一番避けたいことです。小さなプロジェクトであれば関係を整理することは可能ですが、要件がどんどん増えていくと、単純に考えても無理があります。
を始めることです。 サードパーティーの導入により、モジュール間の結合はなく、依存関係は最小化され、IoCによりすべての制御が集中化されます。
を使用した後。 観察しやすいように真ん中のIoCコンテナを取り出してみると、モジュール間の結合がなくなり、一つのモジュールを修正した後は、他のモジュールを考慮する必要がなくなっていることが分かります。

IV. 依存性注入の3つのタイプ

1. コンストラクタ注入

コンストラクタ注入とは、コンストラクタがパラメータで生成したオブジェクトに、依存オブジェクトを注入することです。インジェクションを実現するには、コンストラクタを使用するのが一般的な方法です。

    public class A
    {
        public IB B { get; }
        public A(IB b) => B = b;
    }



ASP.NET Coreでの利用

 [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", " "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            Return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }



2. 属性注入

アノテーションを付けることで InjectionAttribute 属性を自動的に注入される依存属性として設定することができます。

    public class A
    {
        public IB B { get; set; }
        [Injection]
        public IC C { get; set; }
    }



3. メソッドインジェクション

また、マークアップすることで InjectionAttribute 属性を使用すると、そのメソッドをインジェクション・メソッドとしてマークすることができます。

    public class A
    {
        public IB B { get; }
        [Injection]
        public Initialize(IB b) => B = b;
    }




これはサービスのコンテナ初期化時に自動的に呼び出されることで実現されていますが、さらにもうひとつ、より自由な方法でインジェクションを実現するために、このような ASP.NET Core この方法は、広く使われているIn ASP.NET Core が呼び出されます。 Startup オブジェクトを使用してミドルウェアの登録を完了します。一方、Startupタイプは定義時にインターフェイスを実装する必要がないため、登録時の Configure メソッドには決まった宣言はありませんが、このメソッドに任意の依存サービスを以下のメソッドで登録することができます。

  public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "WebApplication1 v1"));
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }



V. ライフサイクル

AddSingletonのライフサイクル。 プロジェクト開始 - プロジェクト終了 静的クラスと同等 1つしかない
AddScoped のライフサイクル。 リクエスト開始 - リクエスト終了 このリクエストで取得されたオブジェクトはすべて同じものである
AddTransient のライフサイクル。 リクエスト取得~(GC回収~アクティブリリース) 各取得は同一オブジェクトではない

注意事項 を使用しているため AddScoped オブジェクトはリクエスト時に作成されるため、このオブジェクトは AddSingleton オブジェクト、あるいは AddTransient オブジェクトを作成します。
重さです。 AddSingleton→AddTransient→AddScoped

Net Coreにはインジェクションが搭載されています 

       public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<IA, A>;
            services.AddSingleton<IB, B>;
            services.AddTransient<IC, C>;
            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" });
            });
        }



注意 ASP.Net Core Net Coreの/codeはまだ比較的シンプルですが、サービスが多くなってくると手動インジェクションが面倒になり、他のIoCフレームワークの導入が後回しになります。

NET Coreの依存性注入は、過去の記事を検索するか、以下の関連記事を引き続き閲覧して、サポートを受けてください