Skip to main content

Lifetime safety

Disposable transients are easy to leak. Resolve one on a long-lived owner and it sits there, undisposed, for the life of that owner. Awaiten guards against this by default, and the guard is a compile-time decision, not a runtime surprise.

Strict is the default

In the strict default, a disposable transient is withheld from by-type resolution on the root. On the root, it would accumulate for the whole life of the container.

[Container] // strict by default
[Transient<BrewSession>] // BrewSession is IDisposable
public static partial class CoffeeShop;

BrewSession session = shop.Resolve<BrewSession>(); // withheld

At runtime this Resolve throws with guidance, and TryResolve returns false. The message steers you toward a bounded option.

A transient with an OnRelease hook is withheld the same way, even when SuppressDisposal opts it out of disposal itself: each construction queues the release on the owner, so on the root the instances pile up just like undisposed ones would.

What is still allowed

Strict mode does not get in your way for the safe shapes:

  • Owned<T> and Func<Owned<T>>, because you control disposal. See Owned.
  • A disposable transient injected into a normal constructor, because its owner disposes it.
  • A disposable transient resolved from a child scope, because the scope bounds its lifetime.
  • A singleton's Lazy<T> over a disposable, because it is memoized and bounded.

What strict withholds is the leak-prone shape: a plain Func<T> or Func<TArg, T> over a disposable, held by a root-owned service. That is a non-suppressible error (AWT118), because each call would strand another undisposed instance on the root. Under Loose it relaxes to a suppressible warning.

Loose when you want MS.DI semantics

Set LifetimeSafety = LifetimeSafety.Loose to make everything resolvable everywhere, the way Microsoft's container behaves. The leak-prone pattern becomes a warning instead of being withheld.

[Container(LifetimeSafety = LifetimeSafety.Loose)]
[Transient<BrewSession>]
public static partial class CoffeeShop;

Reach for Loose when you are bridging to code that expects MS.DI behavior. Otherwise, strict plus Owned<T> keeps disposal honest.

Where to go next

  • Owned for the recommended way to rent disposables.
  • Disposal for the teardown rules.
  • MS.DI bridge for interop with Microsoft's container.