ASP.NET Coreノート(2)-依存注入

4204 ワード

  • サービスのライフサイクル
  • チェーン注入時の生存期間の選択
  • TryAddと汎用注入
  • は、内蔵サービスコンテナ
  • を置き換える.
    ASP.NET Coreはデフォルトの依存注入容器を提供し、Startup.ConfigureServicesメソッドでは、サービス注入の構成を行います.

    サービスのライフサイクル


    デフォルトの依存注入コンテナは、3つのライフサイクルを提供します.
  • 一時(AddTransient)は、サービスコンテナに要求されるたびに新しいインスタンスを作成します.この生存期間は、軽量レベルでステータスのないサービスに適しています.
  • の範囲(AddScoped)で、クライアント要求ごとにインスタンスを作成します.
  • (AddSingleton)は、最初のリクエスト時(またはStartup.ConfigureServicesを実行し、サービス登録指定インスタンスを使用する場合)に作成され、後続のリクエストごとに同じインスタンスが使用されます.アプリケーションが単一の動作を必要とする場合は、サービスコンテナがサービスの生存期間を管理することを許可することを推奨します.単一の設計モデルを自分で実現しないでください.

  • この3つの方法の違いを試してみましょう.注入構成:
    services.AddSingleton();
    services.AddTransient();
    services.AddScoped();
    
    services.AddTransient();
    

    コントローラ:
    public DefaultController(ISingletonTest singleton, ITransientTest transient, IScopedTest scoped, ScopeAndTransientTester scopeAndTransientTester
        )
    {
        this.singleton = singleton;
        this.transient = transient;
        this.scoped = scoped;
        this.scopeAndTransientTester = scopeAndTransientTester;
    }
    
    [HttpGet]
    public string Get()
    {
        return $"singleton={singleton.guid}; \r
    scoped1={scoped.guid};\r
    scoped2={scopeAndTransientTester.ScopedID()};\r
    transient={transient.guid};\r
    transient2={scopeAndTransientTester.TransientID()};"; }

    2回目の注入に使用されるScopeAndTransientTesterクラス:
    public class ScopeAndTransientTester
    {
        public ISingletonTest singleton { get; }
        public ITransientTest transient { get; }
        public IScopedTest scoped { get; }
    
        public ScopeAndTransientTester(ISingletonTest singleton, ITransientTest transient, IScopedTest scoped)
        {
            this.singleton = singleton;
            this.transient = transient;
            this.scoped = scoped;
        }
    
        public Guid SingletonID()
        {
            return singleton.guid;
        }
        public Guid TransientID()
        {
            return transient.guid;
        }
        public Guid ScopedID()
        {
            return scoped.guid;
        }
    }
    

    最初のリクエスト:
    singleton=ebece97f-bd38-431c-9fa0-d8af0419dcff; 
    scoped1=426eb574-8f34-4bd3-80b3-c62366fd4c74;
    scoped2=426eb574-8f34-4bd3-80b3-c62366fd4c74;
    transient=98f0da06-ba8e-4254-8812-efc19931edaa;
    transient2=c19482f7-1eec-4b97-8cb2-2f66937854c4;
    

    2回目のリクエスト:
    singleton=ebece97f-bd38-431c-9fa0-d8af0419dcff; 
    scoped1=f5397c05-a418-4f92-8c6d-78c2c8359bb5;
    scoped2=f5397c05-a418-4f92-8c6d-78c2c8359bb5;
    transient=59ed30fa-609b-46b1-8499-93a95ecd330b;
    transient2=d2a8ea1c-ae0b-4732-b0a1-ca186897e676;
    

    異なるインスタンスをGuidで表します.2回の要求と比較してAddSingleton方式のid値が同じであることがわかる.AddScope方式は2回のリクエストの間で異なるが、同じリクエスト内では同じである.AddTransient方式は同じリクエスト内の複数回の注入間で異なる.

    TryAddと汎用注入


    またTryAdd{Lifetime}方式もあり、同じタイプのサービスが登録されていない場合にのみサービスを追加したい場合に使用できます.Add{Liffetime}をそのまま使用すると、複数回使用すると再登録されます.
    Add{LIFETIME}()という使い方に加えて、この別のリロード方法もあります.
    Add{LIFETIME}(typeof(SERVICE, typeof(IMPLEMENTATION)
    

    この書き方には汎用型を解析できるメリットがあります.ILoggerのようにフレームワークはこのような方法で自動的に登録されています.
    services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
    

    チェーン注入時の生存期間の選択


    依存関係注入をチェーン方式で使用する場合、各リクエストの依存関係は、それに応じて独自の依存関係を要求する.コンテナは、これらの依存関係を解析し、依存ツリーを構築し、完全に解析されたサービスを返します.チェーン注入時には、依存側のライフサイクルが依存側のライフサイクルよりも大きくならないことに注意する必要があります.前の例のScopeAndTransientTesterは、3つのライフサイクルのサービスを注入しているので、一時的に登録するしかありません.そうしないと、起動時にエラーが発生します.
    System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor '*** Lifetime: Singleton ImplementationType: ***': Cannot consume scoped service '***' from singleton 
    

    組み込みサービスコンテナの置き換え


    組み込みサービスコンテナは、フレームワークとほとんどの開発者アプリケーションのニーズを満たすために設計されています.一般的には、組み込みコンテナを使用するだけで十分です.属性注入、名前ベース注入、サブコンテナ、カスタムライフサイクル管理、遅延初期化のFuncサポート、約束ベースの登録など、組み込みコンテナでサポートされていない特定の機能を使用する必要がない限り、十分です.