Когда устанавливаются инъецируемые экземпляры .NET Core?

ASP.NET Core использует методы расширения в IServiceCollection для установки инъекции зависимостей, а затем, когда нужен тип, он использует соответствующий метод для создания нового экземпляра:

  • AddTransient<T> - добавляет тип, который создается снова при каждом запросе.
  • AddScoped<T> - добавляет тип, который сохраняется для области запроса.
  • AddSingleton<T> - добавляет тип при первом запросе и сохраняет его.

У меня есть типы, которые реализуют IDisposable, и это вызовет проблемы, если они не будут удалены - в каждом из этих шаблонов, когда на самом деле вызывается Dispose?

Есть ли что-нибудь, что мне нужно добавить (например, обработка исключений), чтобы убедиться, что экземпляр всегда удален?

Ответ 1

Разрешенные объекты имеют один и тот же цикл жизни/времени в качестве своего контейнера, если вы не вручную удаляете временные службы в коде с помощью оператора using или .Dispose().

В ядре ASP.NET вы получаете контейнер с областью действия, который создается для каждого запроса и удаляется в конце запроса. В это время также будут задействованы области видимости и временные зависимости, которые были созданы этим контейнером (что если они реализуют интерфейс IDisposable), который вы также можете увидеть в исходном коде .

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>()), и ваши службы правильно реализуют одноразовый интерфейс (например, указано в MSDN) вам не о чем позаботиться.

Родительский контейнер недоступен вне метода Configure(IApplicationBuilder app), если вы не делаете какие-то напуганные вещи, чтобы сделать его доступным снаружи (что вы не должны в любом случае).

Конечно, его рекомендуется как можно скорее освободить временные услуги, особенно если они потребляют много ресурсов.