Repository navigation
๐ New Features
-
Custom Disposal Strategy (#151) โ tracked singleton and scoped instances can now be wrapped or replaced just before they are released, through the generator-emitted partial methods
OnDispose<T>(ref T)andOnDisposeAsync<T>(ref T).- Enabled by the new hints
Hint.OnDispose,Hint.OnDisposePartial,Hint.OnDisposeAsyncandHint.OnDisposeAsyncPartial. - The same extension point is available for
Owned<T>disposal. - The hooks are off by default, so the generator keeps emitting the direct
Dispose()call with zero overhead, mirroringOnNewInstance. - See
readme/custom-dispose-strategy.mdandreadme/custom-dispose-strategy-for-ownedt.md.
- Enabled by the new hints
-
Multiple Implementations in One Binding โ
To<T1, T2, ...>()binds several implementations to the same contract in a single call. -
Pure.DI.Agent tool โ a new
dotnet-puredi-agent.NET tool installs Pure.DI guidance for Codex and Claude Code into an existing .NET project.- The shipped consumer guidance lives in
agent-context/; both project templates carry copies of it, together with.agents/.claudeskill folders. - See
agent-context.
- The shipped consumer guidance lives in
๐ Improvements
- Generated code for shared instances (#155, #157) โ a Singleton/Scoped instance first created inside an
Owned<T>or under an overriding factory such asFunc<TArg, T>no longer inherits that resolve's accumulators.- Its transient disposable dependencies are no longer added to the enclosing
Owned<T>and disposed with it, so the shared instance is not torn down while still in use. Ensure...Exists()helpers are generated again underOwned<T>andFunc<TArg, T>, so a shared instance is written out once instead of once per dependency path.- Under
Func<TArg, T>the helper is refused only for nodes that actually consume the argument, so each call's argument still reaches its consumers. - The
Owned<T>of a shared instance is now kept separate from theOwned<T>that first creates it, which fixesObjectDisposedExceptionon a laterFunc<Owned<T>>call andCS0103in the generated helper. - An
Owned<T>whose only disposables belong to a singleton now usesOwned.Empty.
- Its transient disposable dependencies are no longer added to the enclosing
๐ Bug Fixes
- Fixed #152: generated code could reference a variable that does not exist in the current context (
CS0103, for example the namelocalWorkerA). - Fixed #154:
ctx.RootTypereturned the wrapping lightweight root type instead of the user's root type. - Fixed #160: a deferred enumerable escaped its scope in cyclic graphs.
- Fixed code generation for nested enumerable factory cycles.
- Fixed the variable scope of a deferred lightweight root.
- Fixed singleton initialization in deferred lightweight roots.
- Fixed simplified bindings exposing
IAsyncDisposableas a contract: a parameterlessBind()no longer infersSystem.IAsyncDisposable, which producedDIW000: The binding for System.IAsyncDisposable has been overriddenwhen two implementations shared that interface.IAsyncDisposableis now excluded explicitly, in line withIDisposable. - Fixed the
DependsOnparams overload, which now accepts multiple setup names. - Fixed namespace resolution in
MetadataWalkerfor internal setups with unique bindings.
โ ๏ธ Behaviour Changes
- A
Transientaccumulator no longer collects the transient dependencies of a singleton created inside it (#155). - A disposable
PerResolveinstance captured by a singleton now belongs to the singleton and is not disposed by theOwned<T>(#155).
๐ Contributors
Thanks to everyone who contributed to this release:
- Emil Kalchev (@ekalchev) โ generated
EnsureโฆExists()helpers for shared instances underOwned<T>andFunc<TArg, T>(#155, #157, PR #158).
Full Changelog: 2.5.4...2.5.5