web-dev-qa-db-ja.com

.NET Coreの依存関係を挿入したインスタンスはいつ破棄されますか?

ASP.NET CoreはIServiceCollectionの拡張メソッドを使用して依存性注入を設定し、型が必要な場合は適切なメソッドを使用して新しいインスタンスを作成します。

  • AddTransient<T>-要求されるたびに再度作成されるタイプを追加します。
  • AddScoped<T>-リクエストのスコープに対して保持されるタイプを追加します。
  • AddSingleton<T>-最初に要求されたときに型を追加し、保持します。

IDisposableを実装するタイプがあり、それが破棄されないと問題が発生します-Disposeが実際に呼び出されるのはこれらのパターンのそれぞれですか?

インスタンスを常に破棄するために追加する必要があるもの(例外処理など)はありますか?

34
Keith

usingステートメントまたは.Dispose()メソッドを使用してコード内で一時サービスを手動で破棄しない限り、解決されたオブジェクトのライフタイム/破棄サイクルはコンテナと同じです。

ASP.NET Coreでは、要求ごとにインスタンス化され、要求の最後に破棄されるスコープコンテナーを取得します。現時点では、このコンテナによって作成されたスコープ依存および一時依存関係も破棄されます(IDisposableインターフェイスを実装している場合)。これはソースコード here でも確認できます。

_public void Dispose()
{
    lock (ResolvedServices)
    {
        if (_disposeCalled)
        {
            return;
        }
        _disposeCalled = true;
        if (_transientDisposables != null)
        {
            foreach (var disposable in _transientDisposables)
            {
                disposable.Dispose();
            }

            _transientDisposables.Clear();
        }

        // PERF: We've enumerating the dictionary so that we don't allocate to enumerate.
        // .Values allocates a ValueCollection on the heap, enumerating the dictionary allocates
        // a struct enumerator
        foreach (var entry in ResolvedServices)
        {
            (entry.Value as IDisposable)?.Dispose();
        }

        ResolvedServices.Clear();
    }
}
_

シングルトンは、親コンテナが破棄されると、通常はアプリケーションがシャットダウンすることを意味します。

TL; DR:アプリケーションの起動時に(app.ApplicationServices.GetService<T>()を使用して)スコープされた/一時的なサービスをインスタンス化しない限り、およびサービスDisposableインターフェースを正しく実装します( MSDNで指摘 など)、注意する必要はありません。

親コンテナは、Configure(IApplicationBuilder app)メソッドの外部では使用できません(何らかの方法でファンキーな操作を行って外部にアクセスできるようにします(とにかくすべきではありません)。

もちろん、特に大量のリソースを消費する場合は、一時的なサービスをできるだけ早く解放することをお勧めします。

38
Tseng