[解決済み] AddTransient、AddScoped、AddSingleton サービスの相違点
質問
を実装したい。
依存性注入
(DI) を ASP.NET Core で使用することができます。そこで、このコードを
ConfigureServices
メソッドを使用すると、両方の方法で動作します。
とはどのような違いがあるのでしょうか。
services.AddTransient
と
service.AddScoped
メソッドを ASP.NET Core で使用できますか?
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddScoped<IEmailSender, AuthMessageSender>();
}
解決方法は?
TL;DR
トランジェントオブジェクトは常に異なるもので、新しいインスタンスが提供されます。 は、すべてのコントローラ、すべてのサービスにおいて
スコープ付きオブジェクトは、1つのリクエスト内では同じだが、他のリクエストでは異なる。 異なるリクエスト
シングルトン オブジェクトは、すべてのオブジェクトとすべてのリクエストで同じです。
より明確にするために、この例では .NETドキュメント は、その違いを示しています。
これらのライフタイムと登録オプションの違いを示すために、1つまたは複数のタスクを一意の識別子で操作として表現するシンプルなインターフェイスを考えてみましょう。
OperationId
. このサービスのライフタイムをどのように設定するかによって、コンテナは要求元のクラスに対してサービスの同じインスタンスまたは異なるインスタンスを提供します。どちらのライフタイムが要求されているかを明確にするために、 ライフタイムオプションごとに1つのタイプを作成します。
using System;
namespace DependencyInjectionSample.Interfaces
{
public interface IOperation
{
Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}
}
これらのインターフェースを1つのクラスを使って実装します。
Operation
コンストラクタでGUIDを受け取り、GUIDが提供されない場合は新しいGUIDを使用します。
using System;
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Classes
{
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
{
Guid _guid;
public Operation() : this(Guid.NewGuid())
{
}
public Operation(Guid guid)
{
_guid = guid;
}
public Guid OperationId => _guid;
}
}
次に
ConfigureServices
各タイプは、その名前の寿命に従ってコンテナに追加されます。
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
ただし
IOperationSingletonInstance
サービスは、ID が既知の特定のインスタンスを使用しています。
Guid.Empty
このため、この型が使用されていることが明確になります。また
OperationService
に依存し、他の
Operation
そのため、このサービスが各操作タイプについて、コントローラと同じインスタンスを取得しているのか、それとも新しいインスタンスを取得しているのかが、リクエスト内で明確になります。このサービスが行うことは、その依存関係をプロパティとして公開し、ビューに表示できるようにすることだけです。
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Services
{
public class OperationService
{
public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance SingletonInstanceOperation { get; }
public OperationService(IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}
}
}
アプリケーションへの個別のリクエスト内、およびリクエスト間のオブジェクトの寿命を示すために、このサンプルには
OperationsController
の各種を要求している。
IOperation
タイプだけでなく
OperationService
. その
Index
アクションは、コントローラとサービスのすべての
OperationId
の値です。
using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
using Microsoft.AspNetCore.Mvc;
namespace DependencyInjectionSample.Controllers
{
public class OperationsController : Controller
{
private readonly OperationService _operationService;
private readonly IOperationTransient _transientOperation;
private readonly IOperationScoped _scopedOperation;
private readonly IOperationSingleton _singletonOperation;
private readonly IOperationSingletonInstance _singletonInstanceOperation;
public OperationsController(OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance singletonInstanceOperation)
{
_operationService = operationService;
_transientOperation = transientOperation;
_scopedOperation = scopedOperation;
_singletonOperation = singletonOperation;
_singletonInstanceOperation = singletonInstanceOperation;
}
public IActionResult Index()
{
// ViewBag contains controller-requested services
ViewBag.Transient = _transientOperation;
ViewBag.Scoped = _scopedOperation;
ViewBag.Singleton = _singletonOperation;
ViewBag.SingletonInstance = _singletonInstanceOperation;
// Operation service has its own requested services
ViewBag.Service = _operationService;
return View();
}
}
}
これで、このコントローラアクションに2つの別々のリクエストが行われるようになりました。
どの
OperationId
の値はリクエスト内、およびリクエスト間で変化します。
-
トランジェントオブジェクトは常に異なるものであり、すべてのコントローラとすべてのサービスに新しいインスタンスが提供されます。
-
スコープされたオブジェクトは、リクエスト内では同じですが、異なるリクエスト間では異なります。
-
シングルトン・オブジェクトは、すべてのオブジェクトとすべてのリクエストで同じです(インスタンスが
ConfigureServices
)
関連
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】文字列が有効な DateTime " format dd/MM/yyyy " として認識されなかった。
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み】バックスラッシュを含むパス文字列のエスケープシーケンスが認識されない件
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] ConfigureServices内からASP.NET Core DIでインスタンスを解決する
-
[解決済み】非同期処理の待ち時間、Wait()でプログラムがフリーズする原因はここにある
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
[解決済み】ORA-01008: すべての変数がバインドされていません。これらはバインドされています。
-
[解決済み】WPFでXamlファイルにコメントを追加する方法は?
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み] EntityTypeにキーが定義されていないエラー
-
[解決済み】"指定されたパスのフォーマットはサポートされていません。"
-
[解決済み】5.7.57 SMTP - MAIL FROMエラー時に匿名メールを送信するためにクライアントが認証されない
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。