Skip to content

Bump DependencyInjection.Lifetime.Analyzers and 3 others#291

Closed
dependabot[bot] wants to merge 1 commit into
masterfrom
dependabot/nuget/src/DNTCommon.Web.Core/tests-be903c31d0
Closed

Bump DependencyInjection.Lifetime.Analyzers and 3 others#291
dependabot[bot] wants to merge 1 commit into
masterfrom
dependabot/nuget/src/DNTCommon.Web.Core/tests-be903c31d0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jul 3, 2026

Copy link
Copy Markdown
Contributor

Updated DependencyInjection.Lifetime.Analyzers from 2.11.42 to 2.18.0.

Release notes

Sourced from DependencyInjection.Lifetime.Analyzers's releases.

2.18.0

DependencyInjection.Lifetime.Analyzers 2.18.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI027: Rx subscription-leak rule (Warning) — the Rx twin of DI025. IObservable<T>.Subscribe(...) returns an IDisposable subscription token instead of needing a -=, so the event-leak proof inverts: where DI025 proves a missing unsubscription, DI027 proves the returned token is discarded. A transient- or scoped-registered service that subscribes an instance-capturing handler (method group, this-capturing lambda, or stored delegate) to an observable exposed by a longer-lived publisher — an injected singleton dependency, or a scoped publisher shared by a transient subscriber — and throws the token away roots every subscriber instance the container creates in the publisher, leaking memory on each resolution and firing stale observers against released state, the same accumulation DI025 catches for events. v1 stays conservative and detects only the highest-confidence discard shapes: an ignored expression statement (obs.Subscribe(H);), a discard assignment (_ = obs.Subscribe(H)), and a local initialized with the token that is never referenced again in the method and is not a using declaration (a real disposal, return, or escape always references the local, so an unreferenced non-using local is provably dropped). The subscribe call is matched FQN-light — any method named Subscribe returning System.IDisposable on a System.IObservable<T> receiver — so System.Reactive, community Rx, and hand-rolled extensions all bind. Reuses DI025's proven infrastructure: EventReceiverClassification (injected-member proven-ctor-assigned, constructor-parameter, and stable chained-projection proofs such as _source.Ticks, via a new ClassifyReceiverExpression entry point that runs DI025's non-static receiver path without the event coupling — DI025's own behavior is byte-for-byte unchanged) and EventHandlerClassification (instance-capture proof), plus DI025's publisher-rank resolution (most conservative registration wins, closed registrations preferred over open-generic fallbacks, keyed-only registrations excluded). Single Warning tier for now — a scoped publisher above a transient subscriber reports Warning rather than an Info tier (scoped-publisher tiering is noted as future work). Documented false negatives, deferred to later passes: tokens stored in a field (dispose-path analysis), using/using var subscriptions, tokens later disposed/returned/passed as arguments, CompositeDisposable/DisposeWith/AddTo/SerialDisposable patterns, the BCL Subscribe(IObserver<T>) overload, and the static ObservableExtensions.Subscribe(source, handler) call form. No code fix this pass — the safe repair is registered-lifetime-dependent like DI025's tier-3 assist and is deferred.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.18.0

What changed

Added

  • DI027: Rx subscription-leak rule (Warning) — the Rx twin of DI025. IObservable<T>.Subscribe(...) returns an IDisposable subscription token instead of needing a -=, so the event-leak proof inverts: where DI025 proves a missing unsubscription, DI027 proves the returned token is discarded. A transient- or scoped-registered service that subscribes an instance-capturing handler (method group, this-capturing lambda, or stored delegate) to an observable exposed by a longer-lived publisher — an injected singleton dependency, or a scoped publisher shared by a transient subscriber — and throws the token away roots every subscriber instance the container creates in the publisher, leaking memory on each resolution and firing stale observers against released state, the same accumulation DI025 catches for events. v1 stays conservative and detects only the highest-confidence discard shapes: an ignored expression statement (obs.Subscribe(H);), a discard assignment (_ = obs.Subscribe(H)), and a local initialized with the token that is never referenced again in the method and is not a using declaration (a real disposal, return, or escape always references the local, so an unreferenced non-using local is provably dropped). The subscribe call is matched FQN-light — any method named Subscribe returning System.IDisposable on a System.IObservable<T> receiver — so System.Reactive, community Rx, and hand-rolled extensions all bind. Reuses DI025's proven infrastructure: EventReceiverClassification (injected-member proven-ctor-assigned, constructor-parameter, and stable chained-projection proofs such as _source.Ticks, via a new ClassifyReceiverExpression entry point that runs DI025's non-static receiver path without the event coupling — DI025's own behavior is byte-for-byte unchanged) and EventHandlerClassification (instance-capture proof), plus DI025's publisher-rank resolution (most conservative registration wins, closed registrations preferred over open-generic fallbacks, keyed-only registrations excluded). Single Warning tier for now — a scoped publisher above a transient subscriber reports Warning rather than an Info tier (scoped-publisher tiering is noted as future work). Documented false negatives, deferred to later passes: tokens stored in a field (dispose-path analysis), using/using var subscriptions, tokens later disposed/returned/passed as arguments, CompositeDisposable/DisposeWith/AddTo/SerialDisposable patterns, the BCL Subscribe(IObserver<T>) overload, and the static ObservableExtensions.Subscribe(source, handler) call form. No code fix this pass — the safe repair is registered-lifetime-dependent like DI025's tier-3 assist and is deferred.

Learn more

2.17.0

DependencyInjection.Lifetime.Analyzers 2.17.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI025/DI026 code fix now creates the disposal path, not just fills it — the fixer previously only inserted the mirrored -= into a Dispose method that already existed; it refused whenever the type had no dispose-shaped method. Two new tiers extend it, both still gated on a method-group handler whose receiver resolves inside Dispose. Tier 2 (inherited contract): when disposability comes from a base type that follows the standard virtual Dispose(bool) pattern, the fix adds a protected override void Dispose(bool disposing) that unsubscribes and chains to base.Dispose(disposing) — overriding the pattern is what guarantees the unsubscribe actually runs, through the base's Dispose()Dispose(true) dispatch. Inherited shapes with no such hook (a non-virtual or explicitly-implemented base Dispose) are refused, because a method the container never calls would be a fake repair. Tier 3 (implement the interface): a subscriber registered scoped that implements neither disposal interface gets IDisposable added to its base list plus a public void Dispose() that unsubscribes; the owning scope disposes it deterministically, so no leak is introduced. To make tier 3 possible without re-running registration collection, the analyzer now stamps the subscriber's registered lifetime into the diagnostic's Properties bag (SubscriberLifetime = Transient/Scoped) — a purely additive change; all diagnostic messages are unchanged. Introducing IDisposable on a transient subscriber is deliberately refused: a disposable transient is exactly the DI008 disposable-transient-capture shape, so the fix must never trade a DI025 for a DI008. DI026 only ever fires for transient subscribers, so its code fix offers tiers 1 and 2 but never tier 3. Lambda hoisting stays refused because it changes capture semantics. Two fixer-output edges were hardened after Codex review: tier 2 now accepts only the NEAREST inherited Dispose(bool) when it is a non-abstract, non-sealed, protected virtual/override hook — a public/protected internal hook (accessibility mismatch, CS0507), an abstract hook (uncallable base.Dispose(disposing)), and a sealed override on an intermediate base are all refused; tier 3 emits a fully-qualified global::System.IDisposable base entry with Simplifier.Annotation so it binds correctly even without using System or against a namespace-local IDisposable, reducing to the shortest unambiguous form. A second Codex-review round hardened three more edges: the added Dispose(bool) override now guards its unsubscribe with if (disposing) so managed state is not touched on the finalizer path; tier 2 additionally verifies the base's parameterless Dispose() actually dispatches to the bool hook in source (a non-dispatching or metadata-only Dispose() is refused, since the override would never run); and the analyzer stamps SubscriberLifetime = Scoped only when the subscriber has a scoped registration and NO transient one, so a subscriber registered both transient and scoped stamps Transient and tier 3 refuses it (its live transient registration is the DI008 risk). A third Codex-review round tightened that dispatch check further: the base's Dispose() must call its OWN hook — a bare Dispose(true) or this.Dispose(true) in its executable body, not inside a nested lambda or local function — so a call that disposes another object (_inner.Dispose(true), base.Dispose(true)), passes false, or never actually runs no longer counts as dispatch and is refused. Finally, the batch fix-all provider is replaced by a custom sequential DocumentBasedFixAllProvider: batch-merging independent edits ran a synthesizing tier once per diagnostic and emitted a duplicate dispose member (or lost unsubscribes) when one type carried several leaks, so the fix-all now tags every subscription up front and re-evaluates each against the evolving document, merging the second leak onward into the member the first one created — one Dispose/override holding every -= (all under the if (disposing) guard for the override tier). A final round closed two more tier-2 fake-repair edges: the override is offered only when the subscriber actually implements System.IDisposable (a base with the dispose shape but no IDisposable contract is never disposed by the container), and the base Dispose() dispatch is now bound with the semantic model and required to resolve to the very hook being overridden — a Dispose(true) that binds to a different Dispose(bool) (for example a grandparent's private hook the container's dispose path actually reaches) no longer counts.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.17.0

What changed

Added

  • DI025/DI026 code fix now creates the disposal path, not just fills it — the fixer previously only inserted the mirrored -= into a Dispose method that already existed; it refused whenever the type had no dispose-shaped method. Two new tiers extend it, both still gated on a method-group handler whose receiver resolves inside Dispose. Tier 2 (inherited contract): when disposability comes from a base type that follows the standard virtual Dispose(bool) pattern, the fix adds a protected override void Dispose(bool disposing) that unsubscribes and chains to base.Dispose(disposing) — overriding the pattern is what guarantees the unsubscribe actually runs, through the base's Dispose()Dispose(true) dispatch. Inherited shapes with no such hook (a non-virtual or explicitly-implemented base Dispose) are refused, because a method the container never calls would be a fake repair. Tier 3 (implement the interface): a subscriber registered scoped that implements neither disposal interface gets IDisposable added to its base list plus a public void Dispose() that unsubscribes; the owning scope disposes it deterministically, so no leak is introduced. To make tier 3 possible without re-running registration collection, the analyzer now stamps the subscriber's registered lifetime into the diagnostic's Properties bag (SubscriberLifetime = Transient/Scoped) — a purely additive change; all diagnostic messages are unchanged. Introducing IDisposable on a transient subscriber is deliberately refused: a disposable transient is exactly the DI008 disposable-transient-capture shape, so the fix must never trade a DI025 for a DI008. DI026 only ever fires for transient subscribers, so its code fix offers tiers 1 and 2 but never tier 3. Lambda hoisting stays refused because it changes capture semantics. Two fixer-output edges were hardened after Codex review: tier 2 now accepts only the NEAREST inherited Dispose(bool) when it is a non-abstract, non-sealed, protected virtual/override hook — a public/protected internal hook (accessibility mismatch, CS0507), an abstract hook (uncallable base.Dispose(disposing)), and a sealed override on an intermediate base are all refused; tier 3 emits a fully-qualified global::System.IDisposable base entry with Simplifier.Annotation so it binds correctly even without using System or against a namespace-local IDisposable, reducing to the shortest unambiguous form. A second Codex-review round hardened three more edges: the added Dispose(bool) override now guards its unsubscribe with if (disposing) so managed state is not touched on the finalizer path; tier 2 additionally verifies the base's parameterless Dispose() actually dispatches to the bool hook in source (a non-dispatching or metadata-only Dispose() is refused, since the override would never run); and the analyzer stamps SubscriberLifetime = Scoped only when the subscriber has a scoped registration and NO transient one, so a subscriber registered both transient and scoped stamps Transient and tier 3 refuses it (its live transient registration is the DI008 risk). A third Codex-review round tightened that dispatch check further: the base's Dispose() must call its OWN hook — a bare Dispose(true) or this.Dispose(true) in its executable body, not inside a nested lambda or local function — so a call that disposes another object (_inner.Dispose(true), base.Dispose(true)), passes false, or never actually runs no longer counts as dispatch and is refused. Finally, the batch fix-all provider is replaced by a custom sequential DocumentBasedFixAllProvider: batch-merging independent edits ran a synthesizing tier once per diagnostic and emitted a duplicate dispose member (or lost unsubscribes) when one type carried several leaks, so the fix-all now tags every subscription up front and re-evaluates each against the evolving document, merging the second leak onward into the member the first one created — one Dispose/override holding every -= (all under the if (disposing) guard for the override tier). A final round closed two more tier-2 fake-repair edges: the override is offered only when the subscriber actually implements System.IDisposable (a base with the dispose shape but no IDisposable contract is never disposed by the container), and the base Dispose() dispatch is now bound with the semantic model and required to resolve to the very hook being overridden — a Dispose(true) that binds to a different Dispose(bool) (for example a grandparent's private hook the container's dispose path actually reaches) no longer counts.

Learn more

2.16.0

DependencyInjection.Lifetime.Analyzers 2.16.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI025/DI026 delegate-field subscriptions — closes a false negative the docs previously half-attributed to events. C# forbids assigning another type's field-like event, so the cross-type delegate leak actually lives on a public delegate-typed field or property of the publisher: _bus.Handlers += OnMessage and the equivalent self-assignment _bus.Handlers = (EventHandler)Delegate.Combine(_bus.Handlers, OnMessage) now report identically to an event += (singleton publisher → DI025 Warning, scoped publisher → DI026 Info), with a mirrored Delegate.Remove self-assignment recognized as the matching unsubscription. Only the trivially-provable self-assignment form is reported — the first Delegate.Combine argument must be the same member the result is assigned back to, reached through the same receiver — so indirect shapes (result stored in a local or a different member) stay silent. This required generalizing the subscription record's member from IEventSymbol to ISymbol and teaching the handler classifier to resolve the single unambiguous method-group candidate that a bare Delegate.Combine argument leaves with a null symbol (no single target delegate type). It matters because event-style delegate accumulation on a long-lived publisher roots every subscriber the container creates, exactly like an event +=, and was invisible before.
  • DI025 guardrail pins — five behaviors are now regression-pinned: a weak-event helper method call (WeakEventManager.AddHandler(...)) stays silent (not a +=/Combine), a static-event -= in Dispose suppresses, a scoped subscriber on a static (process-lifetime) event reports DI025 at Warning and never the DI026 Info tier, a branch-conditional -= (if (_attached) { _bus.E -= H; }) suppresses unconditionally, and a self-unsubscribing handler (_bus.E -= OnMessage inside the handler body) stays silent. The branch-conditional suppression is a deliberate, documented false negative that favours FP-safety over proving the guard always runs.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.16.0

What changed

Added

  • DI025/DI026 delegate-field subscriptions — closes a false negative the docs previously half-attributed to events. C# forbids assigning another type's field-like event, so the cross-type delegate leak actually lives on a public delegate-typed field or property of the publisher: _bus.Handlers += OnMessage and the equivalent self-assignment _bus.Handlers = (EventHandler)Delegate.Combine(_bus.Handlers, OnMessage) now report identically to an event += (singleton publisher → DI025 Warning, scoped publisher → DI026 Info), with a mirrored Delegate.Remove self-assignment recognized as the matching unsubscription. Only the trivially-provable self-assignment form is reported — the first Delegate.Combine argument must be the same member the result is assigned back to, reached through the same receiver — so indirect shapes (result stored in a local or a different member) stay silent. This required generalizing the subscription record's member from IEventSymbol to ISymbol and teaching the handler classifier to resolve the single unambiguous method-group candidate that a bare Delegate.Combine argument leaves with a null symbol (no single target delegate type). It matters because event-style delegate accumulation on a long-lived publisher roots every subscriber the container creates, exactly like an event +=, and was invisible before.

Changed

  • DI025 guardrail pins — five behaviors are now regression-pinned: a weak-event helper method call (WeakEventManager.AddHandler(...)) stays silent (not a +=/Combine), a static-event -= in Dispose suppresses, a scoped subscriber on a static (process-lifetime) event reports DI025 at Warning and never the DI026 Info tier, a branch-conditional -= (if (_attached) { _bus.E -= H; }) suppresses unconditionally, and a self-unsubscribing handler (_bus.E -= OnMessage inside the handler body) stays silent. The branch-conditional suppression is a deliberate, documented false negative that favours FP-safety over proving the guard always runs.

Learn more

2.15.0

DependencyInjection.Lifetime.Analyzers 2.15.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI025/DI026 internals: receiver/handler classification extracted into shared infrastructure — no behavior change (the full 1964-test suite is byte-identical). The analyzer had grown to 2.6x the 500-line structural budget with ReportLeakedSubscriptions at cyclomatic complexity 28; receiver classification (chain walking, stable-projection proofs, canonicalization, injection provenance) now lives in Infrastructure/EventReceiverClassification.cs and handler classification (capture analysis, identity matching) in Infrastructure/EventHandlerClassification.cs, with the reporting pass decomposed into single-purpose gates. The extraction also positions the planned Rx subscription-leak rule (DI027) to reuse receiver classification instead of duplicating it.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.15.0

What changed

Changed

  • DI025/DI026 internals: receiver/handler classification extracted into shared infrastructure — no behavior change (the full 1964-test suite is byte-identical). The analyzer had grown to 2.6x the 500-line structural budget with ReportLeakedSubscriptions at cyclomatic complexity 28; receiver classification (chain walking, stable-projection proofs, canonicalization, injection provenance) now lives in Infrastructure/EventReceiverClassification.cs and handler classification (capture analysis, identity matching) in Infrastructure/EventHandlerClassification.cs, with the reporting pass decomposed into single-purpose gates. The extraction also positions the planned Rx subscription-leak rule (DI027) to reuse receiver classification instead of duplicating it.

Learn more

2.14.0

DependencyInjection.Lifetime.Analyzers 2.14.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI025/DI026 chained receivers — closes the rules' top documented false negative. _host.Bus.Changed += OnChanged now reports when the publisher is a stable projection of an injected chain root: the lifetime proof anchors on the chain root's registration (singleton root → DI025 Warning, scoped root → DI026 Info), and every intermediate segment must provably return the same instance for the root's whole lifetime — a readonly field, a get-only auto-property, or a getter returning one, with interface segments proven through the root's registered implementation types. Settable, computed, metadata-only, and virtual segments keep the chain silent (a _factory.Bus computed getter handing out a fresh bus per access must not warn), as do factory registrations with no visible implementation type and chain roots that are not provably injected. Unsubscription matching is path-aware: a -= through the same chain suppresses (constructor-parameter roots unify with the field they are stored into), while a -= through a different root still reports.
  • DI025/DI026 code fix for chained receivers: the mirrored--= Dispose insertion now covers field/property-rooted chains — the cloned chain re-resolves verbatim inside Dispose. Constructor-parameter-rooted chains are refused (the cloned statement would not compile), matching the existing direct-receiver gate.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.14.0

What changed

Added

  • DI025/DI026 chained receivers — closes the rules' top documented false negative. _host.Bus.Changed += OnChanged now reports when the publisher is a stable projection of an injected chain root: the lifetime proof anchors on the chain root's registration (singleton root → DI025 Warning, scoped root → DI026 Info), and every intermediate segment must provably return the same instance for the root's whole lifetime — a readonly field, a get-only auto-property, or a getter returning one, with interface segments proven through the root's registered implementation types. Settable, computed, metadata-only, and virtual segments keep the chain silent (a _factory.Bus computed getter handing out a fresh bus per access must not warn), as do factory registrations with no visible implementation type and chain roots that are not provably injected. Unsubscription matching is path-aware: a -= through the same chain suppresses (constructor-parameter roots unify with the field they are stored into), while a -= through a different root still reports.
  • DI025/DI026 code fix for chained receivers: the mirrored--= Dispose insertion now covers field/property-rooted chains — the cloned chain re-resolves verbatim inside Dispose. Constructor-parameter-rooted chains are refused (the cloned statement would not compile), matching the existing direct-receiver gate.

Learn more

2.13.0

DependencyInjection.Lifetime.Analyzers 2.13.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI026 (new rule): event subscription on scoped publisher without unsubscribe — the scope-bounded Info tier of DI025, sharing its analyzer (the DI021/DI022 precedent). A transient service that subscribes an instance-capturing handler to an event on a scoped registered publisher, with no matching -= anywhere in the type, now reports at Info: every transient the scope resolves stays rooted in the publisher's delegate list until the scope is disposed, and the event keeps invoking handlers on released instances — mostly benign in per-request scopes, a real accumulation in long-lived ones (SignalR connections, Blazor circuits, hosted-service loop scopes). Raise per team policy with dotnet_diagnostic.DI026.severity = warning. All DI025 receiver/handler/unsubscription proofs, guardrails, and the three message arms carry over unchanged; scoped subscribers on scoped publishers stay silent (equal lifetimes are torn down together). Three previously-silent cells now report DI026: the plain scoped-publisher/transient-subscriber pairing, open-generic scoped publishers injected as constructed closures, and — because the most conservative registration wins — publishers registered both scoped and singleton, including a closed scoped registration overriding an open-generic singleton.
  • DI026 code fix: the DI025 mirrored--= Dispose insertion now also fixes DI026 diagnostics, with the same method-group, disposal-contract, and receiver-availability gates.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.13.0

What changed

Added

  • DI026 (new rule): event subscription on scoped publisher without unsubscribe — the scope-bounded Info tier of DI025, sharing its analyzer (the DI021/DI022 precedent). A transient service that subscribes an instance-capturing handler to an event on a scoped registered publisher, with no matching -= anywhere in the type, now reports at Info: every transient the scope resolves stays rooted in the publisher's delegate list until the scope is disposed, and the event keeps invoking handlers on released instances — mostly benign in per-request scopes, a real accumulation in long-lived ones (SignalR connections, Blazor circuits, hosted-service loop scopes). Raise per team policy with dotnet_diagnostic.DI026.severity = warning. All DI025 receiver/handler/unsubscription proofs, guardrails, and the three message arms carry over unchanged; scoped subscribers on scoped publishers stay silent (equal lifetimes are torn down together). Three previously-silent cells now report DI026: the plain scoped-publisher/transient-subscriber pairing, open-generic scoped publishers injected as constructed closures, and — because the most conservative registration wins — publishers registered both scoped and singleton, including a closed scoped registration overriding an open-generic singleton.
  • DI026 code fix: the DI025 mirrored--= Dispose insertion now also fixes DI026 diagnostics, with the same method-group, disposal-contract, and receiver-availability gates.

Learn more

2.12.0

DependencyInjection.Lifetime.Analyzers 2.12.0

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI025 (new rule): event subscription on longer-lived publisher without unsubscribe — a transient/scoped service that subscribes an instance-capturing handler to an event on an injected singleton dependency or a static event, with no matching -= anywhere in the type, now reports. The publisher's delegate list roots every subscriber instance the container ever creates — the classic .NET event-handler memory leak, caught lifetime-aware. Handler identity is symbol-based, so the no-op unsubscribe bug (-= with a distinct but textually identical lambda) still reports and points at the ineffective -=; override chains are normalized so a base-class -= pairs with a derived-class +=. Singleton subscribers, matching unsubscriptions, static/this-free handlers, non-injected publishers, and unknown shapes all stay silent.
  • DI025 code fix: when the handler is a method group whose receiver resolves inside Dispose and the type already declares a block-bodied Dispose()/Dispose(bool)/DisposeAsync() implementing the matching disposal interface, the fix inserts the mirrored -= at the top of that method. Introducing IDisposable is intentionally not offered (it would change container disposal tracking and trip DI008 on transients).

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.12.0

What changed

Added

  • DI025 (new rule): event subscription on longer-lived publisher without unsubscribe — a transient/scoped service that subscribes an instance-capturing handler to an event on an injected singleton dependency or a static event, with no matching -= anywhere in the type, now reports. The publisher's delegate list roots every subscriber instance the container ever creates — the classic .NET event-handler memory leak, caught lifetime-aware. Handler identity is symbol-based, so the no-op unsubscribe bug (-= with a distinct but textually identical lambda) still reports and points at the ineffective -=; override chains are normalized so a base-class -= pairs with a derived-class +=. Singleton subscribers, matching unsubscriptions, static/this-free handlers, non-injected publishers, and unknown shapes all stay silent.
  • DI025 code fix: when the handler is a method group whose receiver resolves inside Dispose and the type already declares a block-bodied Dispose()/Dispose(bool)/DisposeAsync() implementing the matching disposal interface, the fix inserts the mirrored -= at the top of that method. Introducing IDisposable is intentionally not offered (it would change container disposal tracking and trip DI008 on transients).

Learn more

2.11.43

DependencyInjection.Lifetime.Analyzers 2.11.43

Compile-time DI diagnostics for Microsoft.Extensions.DependencyInjection projects that want earlier feedback on lifetime bugs, scope leaks, service locator drift, and unresolvable registrations.

Why install or upgrade

  • DI014 Dispose(bool) pattern: root providers stored on fields or properties are now recognized as disposed when the standard Dispose() method calls Dispose(true) and the Dispose(bool) overload disposes the provider.
  • DI013 implicit conversion audit: pinned a regression test proving user-defined implicit conversion registrations already report as implementation mismatches instead of being treated as DI-compatible.

Install

dotnet add package DependencyInjection.Lifetime.Analyzers --version 2.11.43

What changed

Fixed

  • DI014 Dispose(bool) pattern: root providers stored on fields or properties are now recognized as disposed when the standard Dispose() method calls Dispose(true) and the Dispose(bool) overload disposes the provider.
  • DI013 implicit conversion audit: pinned a regression test proving user-defined implicit conversion registrations already report as implementation mismatches instead of being treated as DI-compatible.

Learn more

Commits viewable in compare view.

Updated Microsoft.Extensions.Http.Polly from 9.0.0 to 9.0.17.

Release notes

Sourced from Microsoft.Extensions.Http.Polly's releases.

9.0.17

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.16...v9.0.17

9.0.16

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.15...v9.0.16

9.0.15

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.14...v9.0.15

9.0.14

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.13...v9.0.14

9.0.13

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.12...v9.0.13)

9.0.12

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.11...v9.0.12

9.0.11

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.10...v9.0.11

9.0.10

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.9...v9.0.10

9.0.9

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.8...v9.0.9

9.0.7

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.6...v9.0.7

9.0.6

Bug Fixes

  • Forwarded Headers Middleware: Ignore X-Forwarded-Headers from Unknown Proxy (#​61622)
    The Forwarded Headers Middleware now ignores X-Forwarded-Headers sent from unknown proxies. This change improves security by ensuring that only trusted proxies can influence forwarded header values, preventing potential spoofing or misrouting issues.

Dependency Updates

  • Bump src/submodules/googletest from 52204f7 to 04ee1b4 (#​61762)
    Updates the GoogleTest submodule to a newer commit, bringing in the latest improvements and bug fixes from the upstream project.
  • Update dependencies from dotnet/arcade (#​61714)
    Updates internal build and infrastructure dependencies from the dotnet/arcade repository, ensuring compatibility and access to the latest build tools.
  • Update dependencies from dotnet/extensions (#​61571)
    Refreshes dependencies from the dotnet/extensions repository, incorporating the latest features and fixes from the extensions libraries.
  • Update dependencies from dotnet/extensions (#​61877)
    Further updates dependencies from dotnet/extensions, ensuring the project benefits from recent improvements and bug fixes.
  • Update dependencies from dotnet/arcade (#​61892)
    Additional updates to build and infrastructure dependencies from dotnet/arcade, maintaining up-to-date tooling and build processes.

Miscellaneous

  • Update branding to 9.0.6 (#​61831)
    Updates the project version and branding to 9.0.6, reflecting the new release and ensuring version consistency across the codebase.
  • Merging internal commits for release/9.0 (#​61925)
    Incorporates various internal commits into the release/9.0 branch, ensuring that all relevant changes are included in this release.

This summary is generated and may contain inaccuracies. For complete details, please review the linked pull requests.

Full Changelog: v9.0.5...v9.0.6

9.0.5

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.4...v9.0.5

9.0.4

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.3...v9.0.4

9.0.3

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.2...v9.0.3

9.0.2

Release

What's Changed

Full Changelog: dotnet/aspnetcore@v9.0.1...v9.0.2

9.0.1

Release

What's Changed

Description has been truncated

Bumps DependencyInjection.Lifetime.Analyzers from 2.11.42 to 2.18.0
Bumps Microsoft.Extensions.Http.Polly from 9.0.0 to 9.0.17
Bumps System.IO.Hashing from 10.0.8 to 10.0.9
Bumps System.ServiceModel.Syndication from 9.0.0 to 9.0.17

---
updated-dependencies:
- dependency-name: DependencyInjection.Lifetime.Analyzers
  dependency-version: 2.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: tests
- dependency-name: Microsoft.Extensions.Http.Polly
  dependency-version: 9.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tests
- dependency-name: System.IO.Hashing
  dependency-version: 10.0.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tests
- dependency-name: System.ServiceModel.Syndication
  dependency-version: 9.0.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: tests
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added .NET Pull requests that update .net code dependencies Pull requests that update a dependency file labels Jul 3, 2026
@dependabot @github

dependabot Bot commented on behalf of github Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #292.

@dependabot dependabot Bot closed this Jul 3, 2026
@dependabot dependabot Bot deleted the dependabot/nuget/src/DNTCommon.Web.Core/tests-be903c31d0 branch July 3, 2026 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file .NET Pull requests that update .net code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants