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