ASP.NET Coreノート(2)-依存注入
4204 ワード
ASP.NET Coreはデフォルトの依存注入容器を提供し、Startup.ConfigureServicesメソッドでは、サービス注入の構成を行います.
サービスのライフサイクル
デフォルトの依存注入コンテナは、3つのライフサイクルを提供します.
この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サポート、約束ベースの登録など、組み込みコンテナでサポートされていない特定の機能を使用する必要がない限り、十分です.