Жизненный цикл зависимостей

Последнее обновление: 17.05.2022

Встроенный механизм внедрения зависимостей в ASP.NET Core позволяет управлять жизненным циклом внедряемых в приложении сервисов. С точки зрения жизненного цикла сервисы могут представлять один из следующих типов:

  • Transient: при каждом обращении к сервису создается новый объект сервиса. В течение одного запроса может быть несколько обращений к сервису, соответственно при каждом обращении будет создаваться новый объект. Подобная модель жизненного цикла наиболее подходит для легковесных сервисов, которые не хранят данных о состоянии

  • Scoped: для каждого запроса создается свой объект сервиса. То есть если в течение одного запроса есть несколько обращений к одному сервису, то при всех этих обращениях будет использоваться один и тот же объект сервиса.

  • Singleton: объект сервиса создается при первом обращении к нему, все последующие запросы используют один и тот же ранее созданный объект сервиса

Для создания каждого типа сервиса предназначен соответствующий метод AddTransient(), AddScoped() и AddSingleton().

Для рассмотрения механизма внедрения зависимостей и жизненного цикла возьмем следующий интерфейс ICounter:

Public Interface ICounter
    ReadOnly Property Number As Integer
End Interface

Также определим реализацию этого интерфейса - класс RandomCounter

Class RandomCounter
    Implements ICounter
    
	Shared rnd = New Random()
    Dim _number As Integer
    Public Sub New()
        _number = rnd.Next(0, 1000000)
    End Sub

    Public ReadOnly Property Number As Integer Implements ICounter.Number
        Get
            Return _number
        End Get
    End Property
End Class

Суть класса RandomCounter состоит в генерации некоторого случайного числа в диапазоне от 0 до 1000000.

И также определим новый класс, который нам более детально поможет разобраться в механизме Depedency Injection. Этот класс назовем CounterService и определим в нем следующий код:

Public Class CounterService
    Public ReadOnly Property Counter As ICounter
    Public Sub New(counter As ICounter)
        Me.Counter = counter
    End Sub
End Class

Данный класс просто устанавливает объект ICounter, передаваемый через конструктор.

Для работы с сервисами определим компонент middleware, который назовем CounterMiddleware:

Imports Microsoft.AspNetCore.Http

Public Class CounterMiddleware
    Dim i = 0 'счетчик запросов
    Public Sub New(nextMiddleware As RequestDelegate)
    End Sub
    Public Async Function InvokeAsync(httpContext As HttpContext, counter As ICounter, countService As CounterService) As Task

        i += 1
        httpContext.Response.ContentType = "text/html;charset=utf-8"
        Await httpContext.Response.WriteAsync($"Запрос {i}; Counter: {counter.Number}; Service: {countService.Counter.Number}")
    End Function
End Class

Для получения зависимостей здесь используется метод InvokeAsync, в котором передаются две зависимости ICounter и CounterService. В самом методе выводятся значения Value из обоих зависимостей. Причем сервис CounterService сам использует зависимость ICounter.

То есть структура проекта будет выглядеть следующим образом:

Жизненный цикл зависимостей и сервисов в ASP.NET Core и Visual Basic .NET

Теперь на примере этих классов рассмотрим уравление жизненным циклом сервисов.

AddTransient

Метод AddTransient() создает transient-объекты. Такие объекты создаются при каждом обращении к ним. Данный метод имеет ряд перегруженных версий:

  • AddTransient(serviceType As Type)

  • AddTransient(serviceType As Type, implementationType As Type)

  • AddTransient(serviceType As Type, Func(Of IServiceProvider, Object) implementationFactory)

  • AddTransient(Of TService)()

  • AddTransient(Of TService, TImplementation)()

  • AddTransient(Of TService)(Func(Of IServiceProvider,TService) implementationFactory)

  • AddTransient(Of TService, TImplementation)(Func(Of IServiceProvider, TImplementation) implementationFactory)

Используем данный метод для добавления сервисов в файле Program.vb:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.Extensions.DependencyInjection

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)

        builder.Services.AddTransient(Of ICounter, RandomCounter)()
        builder.Services.AddTransient(Of CounterService)()

        Dim app = builder.Build()

        app.UseMiddleware(Of CounterMiddleware)()
        app.Run()
    End Sub
End Module

Запустим проект:

AddTransient в ASP.NET Core и Visual Basic .NET

В нашем случае CounterMiddleware получает объект ICounter, для которого создается один экземпляр класса RandomCounter. CounterMiddleware также получает объект CounterService, который также использует ICounter. И для этого ICounter будет создаваться второй экземпляр класса RandomCounter. Поэтому генерируемые случайные числа обоими экземплярами не совпадают. Таким образом, применение AddTransient создаст два разных объекта RandomCounter.

При втором и последующих запросах к контроллеру будут создаваться новые объекты RandomCounter.

AddScoped

Метод AddScoped создает один экземпляр объекта для всего запроса. Он имеет те же перегруженные версии, что и AddTransient. Для его применения изменим код приложения следующим образом:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.Extensions.DependencyInjection

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)

        builder.Services.AddScoped(Of ICounter, RandomCounter)()
        builder.Services.AddScoped(Of CounterService)()

        Dim app = builder.Build()

        app.UseMiddleware(Of CounterMiddleware)()
        app.Run()
    End Sub
End Module
AddScoped в ASP.NET Core и Visual Basic .NET

Теперь в рамках одного и того же запроса и CounterMiddleware и сервис CounterService будут использовать один и тот же объект RandomCounter. При следующем запросе к приложению будет генерироваться новый объект RandomCounter.

AddSingleton

AddSingleton создает один объект для всех последующих запросов, при этом объект создается только тогда, когда он непосредственно необходим. Этот метод имеет все те же перегруженые версии, что и AddTransient и AddScoped.

Для применения AddSingleton изменим код приложения:

Imports Microsoft.AspNetCore.Builder
Imports Microsoft.Extensions.DependencyInjection

Module Program
    Sub Main(args As String())

        Dim builder = WebApplication.CreateBuilder(args)

        builder.Services.AddSingleton(Of ICounter, RandomCounter)()
        builder.Services.AddSingleton(Of CounterService)()

        Dim app = builder.Build()

        app.UseMiddleware(Of CounterMiddleware)()
        app.Run()
    End Sub
End Module

Как можно заметить, все три метода внедрения зависимостей имеют один и тот же принцип использования, различается только название метода. И в этом случае при нескольких последовательных запросах мы получим следующий результат:

AddSingleton в ASP.NET Core и Visual Basic .NET
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850