Как удалить службу, реализующую IAsyncDisposable, с помощью внедрения зависимостей в .NET 7

У меня есть служба, которая использует этот интерфейс, поскольку она содержит объект, имеющий сам интерфейс.

      public class AddressImporter : IAddressImporter
{
    private readonly IConsumer<Model> _consumer; // implementing IAsyncDisposable
}

Я регистрирую сервис следующим образом:services.AddTransient<IAddressImporter, AddressImporter>();И внедрите его в мой основной сервис следующим образом:

      public MainService(IAddressImporter addressImporter) {
    _addressImporter = addressImporter;
}

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

Я думал добавитьIAsyncDisposableкIAddressImporterи звонюIAddressImporter.DisposeAsyncв случае любого исключения или окончания моегоMainService.

РЕДАКТИРОВАТЬ: При попытке использовать услугу

      public class AddressImporter : IAddressImporter
{
    private readonly IConsumer<Model> _consumer; // implementing IAsyncDisposable
    public async ValueTask DisposeAsync()
    {
        _logger.Information("Disposing {ResourceName}", nameof(PulsarAddressImporter));
        await _consumer.DisposeAsync();
        GC.SuppressFinalize(this);
    }

}

Я получаю исключение:

Ошибка BackgroundService System.InvalidOperationException: тип «AddressService.Web.Jobs.Test» реализует только IAsyncDisposable. Используйте DisposeAsync, чтобы удалить контейнер. System.InvalidOperationException: тип AddressService.Web.Jobs.Test реализует только IAsyncDisposable. Используйте DisposeAsync, чтобы удалить контейнер. [15:23:56 INF] Приложение закрывается...

1 ответ

Будет ли это утечка ресурса?

Это зависит от жизненного цикла родительского объекта и области действия — сервисы, созданные встроенным DI-контейнером, удаляются автоматически при удалении области:

      class MyTransient : IAsyncDisposable
{
    public bool Disposed { get; set; }
    public ValueTask DisposeAsync()
    {
        Disposed = true;
        return ValueTask.CompletedTask;
    }
}

var services = new ServiceCollection();
services.AddTransient<MyTransient>();

var serviceProvider = services.BuildServiceProvider();
MyTransient myTransient;
await using (var scope = serviceProvider.CreateAsyncScope())
{
    myTransient = scope.ServiceProvider.GetRequiredService<MyTransient>();
}

Console.WriteLine(myTransient.Disposed); // prints True

Таким образом, если служба не создана из корневого, она будет удалена со всем остальным, когда закончится область действия владельца, поэтому созданиеAddressImporterвнедрениеIDisposable/IAsyncDisposableдолжно помочь (если исключение приводит к завершению области действия владельца).

Другие вопросы по тегам