DI017

Circular Dependency

High-confidence activation cycles such as A -> B -> A, including longer transitive loops through constructors, explicit GetRequiredService / GetRequiredKeyedService factory calls, ActivatorUtilities factory construction, keyed-service inheritance, open-generic registrations, exact closed registrations that override open-generic fallbacks, and registered IEnumerable<T> elements. It analyzes only reachable service-registration flows and mirrors the default container's constructor-set rule: equivalent reordered greedy constructors expose the same cycle, while a greediest constructor whose resolved service identifiers (type plus key) are not a superset of every other resolvable constructor stays silent as ambiguous.

Warning Default severity · Code fix: No

Why it matters

The default DI container cannot resolve circular constructor graphs and will fail at runtime when the service is activated.

If two people each wait for the other to hand over the key first, the door never opens.

README problem example

services.AddScoped<IOrderService, OrderService>();
services.AddScoped<IPaymentService, PaymentService>();

public sealed class OrderService : IOrderService
{
    public OrderService(IPaymentService payment) { }
}

public sealed class PaymentService : IPaymentService
{
    public PaymentService(IOrderService order) { }
}

Code fix

No. Breaking dependency cycles is a design change.

Repo sample extraction

Examples pulled from the sample app

Open full sample file

Sample app circular dependency

public class BadOrderService : IOrderService
{
    public BadOrderService(IPaymentService payment) { }
}

Sample app safe pattern

public class GoodOrderService : IOrderService { }

Related guides

  • No problem-guide pages point here yet.

Nearby diagnostics

Other rules in this family

All 37 rules