Why it matters
Lifetime mismatch can produce stale state, leaks, and thread-safety defects.
If one pupil keeps the shared class scissors all term, nobody else can use them when needed.
DI003
Singleton services capturing scoped or transient dependencies, including constructor injection, IEnumerable<T> collection captures, known scoped framework services such as IOptionsSnapshot<T>, typed HTTP clients registered with AddHttpClient<TClient>() / AddHttpClient<TClient,TImplementation>(), EF Core contexts and DbContextOptions<TContext> registrations from AddDbContext(...), AddDbContextFactory(...), AddDbContextPool(...), and AddPooledDbContextFactory(...) including service/implementation overload self-registrations, and high-confidence factory paths such as inline delegates, stable local delegate factories, method-group factories, GetServices<T>(), keyed resolutions, and ActivatorUtilities.CreateInstance(...) calls where DI still resolves a scoped or transient constructor parameter. A factory that creates and provably disposes its own scope (using var scope = sp.CreateScope();) stays quiet for resolutions through that scope when only derived values flow into the product — one-time scoped setup is not a captive — while an escaping resolved instance or an undisposed factory scope still reports.
Why it matters
Lifetime mismatch can produce stale state, leaks, and thread-safety defects.
If one pupil keeps the shared class scissors all term, nobody else can use them when needed.
Install
dotnet add package DependencyInjection.Lifetime.Analyzers --version 3.7.8
README problem example
services.AddScoped<IScopedService, ScopedService>();
services.AddSingleton<ISingletonService, SingletonService>();
public sealed class SingletonService : ISingletonService
{
public SingletonService(IScopedService scoped) { }
}
README better pattern
services.AddScoped<ISingletonService, SingletonService>();
// or keep singleton and create scopes inside operations
public sealed class SingletonService : ISingletonService
{
private readonly IServiceScopeFactory _scopeFactory;
public SingletonService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public void Run()
{
using var scope = _scopeFactory.CreateScope();
var scoped = scope.ServiceProvider.GetRequiredService<IScopedService>();
scoped.DoWork();
}
}
Repo sample extraction
Sample app warning case
public class BadSingletonWithScopedDependency
{
private readonly IScopedService _scopedService;
// DI003: Singleton 'BadSingletonWithScopedDependency' captures scoped dependency 'IScopedService'
public BadSingletonWithScopedDependency(IScopedService scopedService)
{
_scopedService = scopedService;
}
public void DoWork() => _scopedService.DoWork();
}
Sample app safe pattern
public class GoodSingletonWithScopeFactory
{
private readonly IServiceScopeFactory _scopeFactory;
public GoodSingletonWithScopeFactory(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public void DoWork()
{
#pragma warning disable DI007 // Factory pattern - IServiceScopeFactory is allowed to resolve services
using var scope = _scopeFactory.CreateScope();
var scopedService = scope.ServiceProvider.GetRequiredService<IScopedService>();
scopedService.DoWork();
#pragma warning restore DI007
}
}
Related guides
More documentation
Nearby diagnostics