如何在.NET 7中使用依赖注入部署实现IAsyncDisposable的服务

wyyhbhjk  于 2023-03-31  发布在  .NET
关注(0)|答案(1)|浏览(139)

我有一个使用IAsyncDisposable接口的服务,因为它持有一个本身具有接口的对象。

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

我这样注册服务:services.AddTransient<IAddressImporter, AddressImporter>();并将其注入到我的主服务中,如下所示:

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

如果是这样,我如何改善这个问题,所以在我的主服务中的任何异常都会调用DisposeAsync
我在考虑将IAsyncDisposable添加到IAddressImporter,并在任何异常或MainService结束时调用IAddressImporter.DisposeAsync
编辑:当尝试使用服务时

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]应用程序正在关闭...

g0czyy6m

g0czyy6m1#

这会不会泄露资源?
这取决于父对象和作用域的生命周期-当作用域被释放时,内置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应该可以做到这一点(如果异常导致所有者作用域结束)。

相关问题