ASP.NET Core依存注入(DI)

10409 ワード

ASP.NET Coreの下位設計は依存注入をサポートし、使用する.ASP.NET Coreアプリケーションは、組み込みフレームワークサービスを利用して起動クラスにサービスを注入する方法があり、アプリケーションサービスも注入を構成することができます.ASP.NET Coreが提供するデフォルトのサービスコンテナは、他のコンテナに取って代わるものではなく、最小の機能セットを提供します.
1.依存注入について
依存注入(Dependency injection,DI)は、直接的に依存項目をインスタンス化したり、静的参照を使用したりするのではなく、クラスがその動作を実行するために使用されるこれらのオブジェクトを注入する方法でクラスに提供する、オブジェクトと依存者との間の緩やかな結合を実現する技術である.一般に、クラスは、関数宣言器2の依存関係を構築することによって、依存を表示する原則に従うことができます.この方法を「構造関数注入」と呼ぶ.
クラスの設計がDI思想を用いると,彼らの結合はより緩やかになる.彼らは協力者に直接ハードコーディングに依存していないからである.これは「依存逆転の原則」に従い、上位モジュールは下位モジュールに依存すべきではないと指摘しています.両方とも抽象に依存しています.
クラスは、特定のインプリメンテーションを参照するのではなく、構築時に抽象(通常はインタフェース)を提供することを要求します.インタフェースの依存関係を抽出し、インタフェースを提供する実装もパラメータとして「ポリシー設計モード」の一例である.
クラスがクラスとそれに関連する依存関係を作成するために使用される場合、これはコンテナ(containers)となり、制御反転(Inversion of Control,IoC)コンテナ、または依存注入コンテナと呼ばれる.コンテナは本質的に工場であり、要求されたタイプのインスタンスを提供する責任を負います.特定のタイプが依存関係を宣言し、コンテナが依存関係を提供するように構成されている場合、依存関係の作成をリクエストインスタンスの作成の一部とします.コンテナは、オブジェクトの依存関係の作成に加えて、アプリケーション内のオブジェクトのライフサイクルを管理します.
ASP.NET Coreには、デフォルトでコンストラクタ注入をサポートする単純な内蔵コンテナ、ASPが含まれています.NETのコンテナとは、StartupクラスのConfigureServicesメソッドに組み込まれたコンテナのサービスを構成できる管理タイプのサービスです.
2.ASPを使用する.NET Coreが提供するサービス
StartupクラスのConfigureServicesメソッドは、Entity Framework CoreやASPなど、プラットフォームが持つ機能を含むアプリケーションが使用するサービスを定義します.NET Core MVC.IServiceCollectionが提供するいくつかのサービスに加えて、いくつかの拡張方法(AddDbContext、AddMvc、AddTransientなど)を使用して、コンテナに追加サービスを追加および登録できます.
public void ConfigureServices(IServiceCollection services)
        {
            services.Configure(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });


            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddDbContext(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                providerOptions => providerOptions.EnableRetryOnFailure()));
            services.AddTransient();

        }

ASP.NET Coreが提供する機能とミドルウェアは、この機能に必要なすべてのサービスを登録するために単一のAddService拡張方法を使用することを約束しています.
3.自分のサービスを登録する
サービスに従ってAddTransient(); この書き方は自分のサービスを登録します.最初のパターンタイプは、コンテナから要求されるタイプ(通常はインタフェース)を表します.2番目のパターンタイプは、コンテナによってインスタンス化され、要求を完了するために使用される特定のタイプを表します.
AddTransientメソッドは、抽象タイプを、必要なオブジェクトごとにインスタンス化された特定のサービスにマッピングするために使用されます.登録されたサービスごとに適切なライフサイクルを選択することが重要です.後述します.
次の例では、独自のサービスを登録します.
1.インタフェース
public interface IAccountServices
    {
        Task> GetList();
    }

2.実装クラス
public class AccountServices:IAccountServices
    {
        AccessManagementContext _context;
        public AccountServices(AccessManagementContext context)
        {
            _context = context;//        
        }

        public async Task> GetList()
        {
            try
            {
                var query = _context.Account.ToListAsync();
                 return query ;
            }
            catch (Exception ex)
            {
                return null;
            }

        }
}

3.ConfigureServicesにカスタムサービスとEFコンテキストAccessManagement Contextを登録する
public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddDbContext(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
                providerOptions => providerOptions.EnableRetryOnFailure()));
            services.AddTransient();

        }

4.Controllerコンストラクション関数での依存注入
public class AccountController : Controller
    {
        private IAccountServices _accountServices;
        public AccountController(IAccountServices accountServices)
        {
            _accountServices = accountServices;
        }
        // GET: Account
        public async Task Index()
        {
            var vms = await _accountServices.GetList();
            return View(vms);
        }

4.サービスのライフサイクルと登録オプション
ASP.NETサービスライフサイクル:
1.Transient瞬時
Transientライフサイクルサービスは、リクエストのたびに作成されます.軽量級、無状態のサービスに適しています.
2.Scopedスコープ
Scopedライフサイクルは、リクエストのたびに作成されます.
3.Singleton単例
Singletonライフサイクルサービスは、最初のリクエスト時に作成され、後続のリクエストごとに同じインスタンスが使用されます.
サービスは、以前の登録方法に加えて、必要なインスタンスを作成するために使用されるファクトリを指定することもできます.他の登録方法については後述します.
各ライフサイクルについて簡単な例を示します.
1.インタフェースの作成:
namespace MVCTest.Interfaces
{
    public interface IOperation
    {
        /// 
        ///     
        /// 
        Guid OperationId { get;  }
    }

    public interface IOperationTransient: IOperation
    {
    }

    public interface IOperationScoped : IOperation
    {
    }

    public interface IOperationSingleton : IOperation
    {
    }

    public interface IOperationInstance : IOperation
    {
    }
}

2.実装クラス
    /// 
    ///       
    /// 
    public class Operation: IOperation, IOperationTransient,
        IOperationScoped, IOperationSingleton, IOperationInstance
    {
        public Operation()
        {
            OperationId = Guid.NewGuid();
        }
        public Operation(Guid operationId)
        {
            if (operationId == null)
            {
                OperationId = Guid.NewGuid();
            }
            OperationId = operationId;
        }

        public Guid OperationId { get; }
    }

3.コンテナへの登録
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient();
            services.AddScoped();
            services.AddSingleton();
            services.AddSingleton();
            services.AddTransient();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

4.インスタンスを使用する場所に関係なく、単一のライフサイクル・サービス(単一のライフサイクル・サービスで最初にインスタンス化されたサービスを使用するすべてのリクエスト)と役割ドメイン・ライフサイクル・サービスをテストするためのOperationServicesも登録されています.
    public class OperationServices
    {
        public IOperationTransient OperationTransient { get;  }
        public IOperationScoped OperationScoped { get;  }
        public IOperationSingleton OperationSingleton { get;  }
        public IOperationInstance OperationInstance { get;  }

        public OperationServices(IOperationTransient operationTransient,
            IOperationScoped operationScoped,
            IOperationSingleton operationSingleton,
            IOperationInstance operationInstance)
        {
            OperationTransient = operationTransient;
            OperationScoped = operationScoped;
            OperationSingleton = operationSingleton;
            OperationInstance = operationInstance;
        }
    }

5.コントローラでの使用
    public class OperationController : Controller
    {
        public IOperationTransient OperationTransient { get; }
        public IOperationScoped OperationScoped { get; }
        public IOperationSingleton OperationSingleton { get; }
        public IOperationInstance OperationInstance { get; }
        public OperationServices _operationServices;

        public OperationController(IOperationTransient operationTransient,
            IOperationScoped operationScoped,
            IOperationSingleton operationSingleton,
            IOperationInstance operationInstance,
            OperationServices operationServices)
        {
            OperationTransient = operationTransient;
            OperationScoped = operationScoped;
            OperationSingleton = operationSingleton;
            OperationInstance = operationInstance;
            _operationServices = operationServices;
        }
        // GET: Operation
        public ActionResult Index()
        {
            ViewBag.OperationTransient = OperationTransient;
            ViewBag.OperationScoped = OperationScoped;
            ViewBag.OperationSingleton = OperationSingleton;
            ViewBag.OperationInstance = OperationInstance;
            ViewBag._operationServices = _operationServices;
            return View();
        }
}

6.Index表示
@{
    ViewData["Title"] = "Index";
}

Controller Operations

OperationTransient: @ViewBag.OperationTransient.OperationId

OperationScoped: @ViewBag.OperationScoped.OperationId

OperationSingleton: @ViewBag.OperationSingleton.OperationId

OperationInstance: @ViewBag.OperationInstance.OperationId

Services Operations

OperationTransient: @ViewBag._operationServices.OperationTransient.OperationId

OperationScoped: @ViewBag._operationServices.OperationScoped.OperationId

OperationSingleton: @ViewBag._operationServices.OperationSingleton.OperationId

OperationInstance: @ViewBag._operationServices.OperationInstance.OperationId


7.運転結果
単一のライフサイクル・サービスが要求されるたびに識別されることがわかります.役割ドメインライフサイクルのサービスで、1回のリクエストで使用される同じインスタンス、2回目のリクエストで新しいインスタンスが作成されます.
5.要求サービス
HttpContextからの一回のASP.NETリクエストで利用可能なサービスはRequestServicesコレクションで公開されている.
リクエスト・サービスは、構成されたサービスとリクエストをアプリケーションの一部として記述します.サブオブジェクトが依存を指定した後、これらの要求を満たすオブジェクトは、ApplicationServicesではなくRequestServicesの対応するタイプを検索することによって得ることができます.
6.設計依存注入サービス
カスタム・サービスでは、静的メソッドと直接的なインスタンス化依存のタイプを使用するのではなく、依存注入によって要求します.(New is Glue)
クラスに依存関係が多すぎる場合は、通常、クラスが多すぎる(単一の職責の原則に違反している)ことを示し、いくつかの職責を移す必要があります.
同様に、ControllerクラスはUIに重点を置くべきであるため、ビジネスロジックやデータアクセスなどの詳細は他のクラスにあるべきである.
7.Autofacコンテナの使用
Autofac
原文アドレスASP.NET Core依存注入(DI)