Why it matters
async disposables (`IAsyncDisposable`) may not be cleaned up correctly with sync disposal patterns.
If a machine needs a proper shutdown button, pulling the plug is not enough.
DI005
`CreateScope()` used in async flows where async disposal is needed.
Why it matters
async disposables (`IAsyncDisposable`) may not be cleaned up correctly with sync disposal patterns.
If a machine needs a proper shutdown button, pulling the plug is not enough.
Install
dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.2.2
README problem example
public async Task RunAsync()
{
using var scope = _scopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<IMyService>();
await service.ExecuteAsync();
}
README better pattern
public async Task RunAsync()
{
await using var scope = _scopeFactory.CreateAsyncScope();
var service = scope.ServiceProvider.GetRequiredService<IMyService>();
await service.ExecuteAsync();
}
Repo sample extraction
Sample app warning case
public async Task Bad_CreateScopeInAsyncMethod()
{
// DI005: Use 'CreateAsyncScope' instead of 'CreateScope' in async method
using var scope = _scopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<IScopedService>();
await Task.Delay(100);
service.DoWork();
}
Sample app safe pattern
public async Task Good_CreateAsyncScope()
{
#pragma warning disable DI007 // Intentional use of IServiceProvider within a valid scope
await using var scope = _scopeFactory.CreateAsyncScope();
var service = scope.ServiceProvider.GetRequiredService<IScopedService>();
await Task.Delay(100);
service.DoWork();
#pragma warning restore DI007
}
Related guides
More documentation