Skip to content

2.5.5

Latest

Choose a tag to compare

@NikolayPianikov NikolayPianikov released this 15 Oct 14:03
· 3 commits to master since this release

๐Ÿš€ 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) and OnDisposeAsync<T>(ref T).

    • Enabled by the new hints Hint.OnDispose, Hint.OnDisposePartial, Hint.OnDisposeAsync and Hint.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, mirroring OnNewInstance.
    • See readme/custom-dispose-strategy.md and readme/custom-dispose-strategy-for-ownedt.md.
  • 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/.claude skill folders.
    • See agent-context.

๐Ÿ›  Improvements

  • Generated code for shared instances (#155, #157) โ€” a Singleton/Scoped instance first created inside an Owned<T> or under an overriding factory such as Func<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 under Owned<T> and Func<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 the Owned<T> that first creates it, which fixes ObjectDisposedException on a later Func<Owned<T>> call and CS0103 in the generated helper.
    • An Owned<T> whose only disposables belong to a singleton now uses Owned.Empty.

๐Ÿ› Bug Fixes

  • Fixed #152: generated code could reference a variable that does not exist in the current context (CS0103, for example the name localWorkerA).
  • Fixed #154: ctx.RootType returned 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 IAsyncDisposable as a contract: a parameterless Bind() no longer infers System.IAsyncDisposable, which produced DIW000: The binding for System.IAsyncDisposable has been overridden when two implementations shared that interface. IAsyncDisposable is now excluded explicitly, in line with IDisposable.
  • Fixed the DependsOn params overload, which now accepts multiple setup names.
  • Fixed namespace resolution in MetadataWalker for internal setups with unique bindings.

โš ๏ธ Behaviour Changes

  • A Transient accumulator no longer collects the transient dependencies of a singleton created inside it (#155).
  • A disposable PerResolve instance captured by a singleton now belongs to the singleton and is not disposed by the Owned<T> (#155).

๐Ÿ™ Contributors

Thanks to everyone who contributed to this release:

Full Changelog: 2.5.4...2.5.5