Releases: DevTeam/Pure.DI
Release list
2.5.2
🚀 New Features
-
Owned and Own Infrastructure Enhancements
- Improved built-in ownership infrastructure for
Owned<T>graphs. - Added
Own.Emptyshared no-op owner for graphs that are known to contain no disposable resources. - Added preallocated ownership storage paths to reduce overhead when the generator knows the expected number of tracked resources.
- Added synchronization-aware
Ownconstruction to coordinate resource registration with disposal when thread safety is enabled. - Added rejection checks for disposed owners: resources added after disposal are immediately disposed and rejected instead of leaking.
- Improved built-in ownership infrastructure for
-
Disposal Exception Tracing
- Generated compositions now continue disposing remaining tracked resources when one resource throws during disposal.
- Added partial
OnDisposeException<T>(T disposableInstance, Exception exception)hooks for tracing cleanup failures. - Added the same tracing pattern for
Owned<T>disposal through the generatedPure.DI.Ownedaccumulator. - See
readme/tracing-exceptions-during-composition-disposal.mdandreadme/tracing-exceptions-during-owned-disposal.md.
🛠 Improvements
-
Owned Disposal Semantics
- Improved nested ownership boundary isolation.
- Refined rollback logic when graph construction fails after disposable resources have already been created.
- Suppressed disposal exceptions so one failing dependency does not prevent cleanup of the rest of the graph.
- Avoided generating empty root
try/catchblocks forOwned<T>factory scenarios when no cleanup work is required.
-
Autofac-Parity Coverage
- Added a comparison test suite for
Owned<T>disposal behavior using Autofac scenarios as a reference. - Expanded integration tests for nested ownership, failed construction rollback, disposal ordering, disposal exceptions, and built-in ownership behavior.
- Added a comparison test suite for
-
Documentation
- Expanded XML documentation for abstractions, attributes, templates, ownership infrastructure, and generated API components.
- Refined README structure and disposal/ownership examples.
What's Changed
New Contributors
Full Changelog: 2.5.1...2.5.2
2.5.1
🚀 New Features
-
Union Type Contracts — Pure.DI now supports preview C# union types as DI contracts.
- Case implementations can be bound to a union contract through implicit case-to-union conversion.
- Union contracts are resolved from a single applicable case binding using generated compile-time conversion code.
- Nested union cases and standard conversion rules are supported.
- Ambiguous case bindings now report
DIE050with candidate details and related binding locations. - Union types are not auto-bound, preventing empty union instances from being created accidentally.
- See
readme/union-types.md.
-
Non-Boxing Union Results
- Added support for allocation-friendly custom union results with direct value-type case storage.
- Pure.DI can bind value-type cases to a union contract without adding reflection, lookup, or wrapper allocation.
- See
readme/non-boxing-union-result.md.
-
Ref-Like and Stack-Only Type Support
- Extended fluent API support for ref-like type arguments, including
Span<T>,ReadOnlySpan<T>, customref structtypes, andwhere T : allows ref struct. - Added support for generic lightweight roots and root arguments with
allows ref struct. - Added support for factory delegates that accept stack-only values.
- Added safe default
Func<ReadOnlySpan<char>, T>roots. - Added array-to-
Span<T>/ReadOnlySpan<T>root argument conversion. - See
readme/span-and-readonlyspan.md,readme/default-func-with-readonlyspan.md, andreadme/allows-ref-struct-factory.md.
- Extended fluent API support for ref-like type arguments, including
-
C# 14 Constructor and Overload Features
- Added support for partial constructor injection.
- Pure.DI now honors
OverloadResolutionPriorityAttributewhen selecting constructors. - Constructor selection with
OrdinalAttributewas refined and documented. - See
readme/partial-constructor-injection.mdandreadme/overload-resolution-priority.md.
-
Method and Member Injection Ordering
OrdinalAttributenow applies consistently to fields, properties, methods, and method parameters.- Method-level ordinal takes precedence; otherwise, the lowest parameter ordinal determines method execution order.
- Required fields and selected
initproperties are initialized before regular member injection. - Custom and inherited member ordinal scenarios are now covered by tests and documentation.
🛡 Diagnostics and Validation
-
Stack-Only Safety Diagnostics
DIE046: stack-only dependency cannot be used with stored lifetimes.DIE047: stack-only dependency cannot be injected into fields or properties.DIE048: stack-only implementation cannot be injected through an interface conversion.DIE049: stack-only dependency cannot be captured in generated delegates or factories.DIW012: warns when stack-only dependencies are injected into heap-type constructors.DIW013: warns when stack-only factory overrides are not synchronized.
-
Union and Overload Diagnostics
DIE050: reports ambiguous union case bindings.DIW014: warns when an injection method may resolve to another overload because ofOverloadResolutionPriority.
⚡ High-Performance Scenarios
- Added new examples for:
- ArrayPool-backed buffers.
- Zero-copy network packet parsing.
- Method injection for hot paths.
- Factory delegates without closure capture.
- Object pooling.
- Struct dependencies.
ThreadSafe = Offfor single-threaded compositions.ValueTask<T>roots.- Non-boxing union results.
🧰 Maintenance
- Updated Roslyn analyzer baseline from
4.8to5.6. - Enabled preview language support for union type scenarios.
Uno Platform Sample Application
- Added a new cross-platform Uno Platform sample application powered by Pure.DI.
- The sample uses the single-project Uno SDK with Skia Desktop and targets
net10.0-desktop. - Demonstrates XAML-friendly virtual composition roots,
DesignTimeCompositionoverrides for tooling, and a sharedCompositionresource without adding a runtime DI container. - Includes dispatcher integration, application/window lifetime disposal, and documentation in
readme/UnoApp.md.
Full Changelog: 2.5.0...2.5.1
2.5.0
❗ Breaking Changes
[Bind]Member Exports Renamed to[Export]— The attribute used to expose fields, properties, and methods as bindings is nowExportAttribute.- Replace member-level
[Bind]usage with[Export]. BindAttributenow represents implementation-level bindings.- Related terminology was aligned from “exposed roots” to “exported roots”; use
RootKinds.Exportedinstead ofRootKinds.Exposed.
- Replace member-level
🚀 New Features
-
Implementation-Level Binding Attributes — Pure.DI can now discover bindings declared directly on implementation types.
- Use
[Bind(typeof(IContract), Lifetime.Singleton, "tag")]to declare contract, lifetime, and tags on a class or struct. - Built-in
Type,Tag, and newLifetimeattributes can now participate in implementation binding metadata. - Multiple contracts and tags in the same attribute group are merged into one binding.
- Separate
Bindattribute groups on the same implementation create separate bindings. - Generic marker contracts such as
typeof(IBox<TT>)are supported for generic implementations. - See
readme/bind-attribute.md.
- Use
-
Custom Binding Attributes
- Custom attributes can now be registered as implementation-level binding metadata.
TypeAttribute<T>(),TagAttribute<T>(), and the newLifetimeAttribute<T>()allow Pure.DI to read contract, tag, and lifetime metadata from custom attribute constructor arguments.- This enables implementation assemblies to describe their DI role while keeping composition setup concise.
- See
readme/custom-bind-attribute.md.
-
Export Attribute for Member-Based Bindings
- New
ExportAttributereplaces member-levelBindAttributefor fields, properties, and methods. - Supports exported members with explicit contract type, lifetime, and tags.
- Generic exported members remain supported.
- See
readme/export-attribute.md.
- New
🛠 Improvements
-
Binding Metadata Validation
- Added diagnostics for invalid implementation-level binding metadata.
- Pure.DI now reports an error when an implementation type has multiple lifetime attributes inside the same binding group.
-
Documentation and Usage Scenarios
- Added new examples for bind type attributes, tag attributes, lifetime attributes, metadata merging, generic contracts, multiple contracts, custom bind attributes, and exported members.
Full Changelog: 2.4.3...2.5.0
2.4.3
This release focuses on improving compatibility, enhancing project templates, and expanding built-in support for standard .NET types.
🚀 New Features
- Native AOT Support: Pure.DI.MS now fully supports Native AOT compilation, enabling better compatibility with modern .NET applications.
- Enhanced Project Templates: Improved templates with automatic version configuration make creating new projects faster and more convenient.
- Extended Built-in Type Support: Added out-of-the-box support for additional .NET standard types including TaskCompletionSource, CultureInfo, IFormatProvider, RandomNumberGenerator, IReadOnlySet, TimeProvider, and StringComparer.
🐞 Bug Fixes
- Improved Native AOT compatibility in Pure.DI.MS.
- Better handling of version placeholders in project templates.
- Optimized code generation for improved performance and reduced overhead.
🎨 Improvements
- More readable generated code with improved formatting and detailed comments.
- Enhanced documentation with better examples and getting started guides.
- Optimized performance by removing unnecessary synchronization in generated code.
Full Changelog: 2.4.2...2.4.3
2.4.2
🚀 Improvements
- Emit
_lockfield only when actually used. The thread-safety_lockfield is no longer emitted in generated compositions when nolock(...)statement references it. Previously it was created conservatively for any composition with overrides, wasting memory on every instance. No behavioral changes for compositions that genuinely require thread safety.
🐛 Bug Fixes
- Fix nullable reference type support. Distinguish
TandT?in DI contracts and fix invalid??generated for nullable generic singleton dependencies.
Full Changelog: 2.4.1...2.4.2
2.4.1
🚀 New Features
Enhanced Code Generation
- Improved type handling and formatting logic for better class diagram generation
- Optimized Local Functions Logic — performance improvements in local function handling
🐛 Bug Fixes
Localization Issues — fixed localization problems across multiple language resource files. Updated all localization strings for Arabic, Bengali, German, Spanish, French, Hebrew, Hindi, Indonesian, Italian, Japanese, Korean, Portuguese, Russian, Thai, Vietnamese, and Chinese
Full Changelog: 2.4.0...2.4.1
2.4.0
❗ Breaking Changes
- Nullable Reference Types — This release introduces full support for nullable reference types, which changes how Pure.DI handles nullable types throughout the pipeline. Code that previously relied on automatic null checks for nullable arguments may need adjustment.
🚀 New Features
-
Nullable Reference Types — Breaking change! Pure.DI now fully preserves nullable reference type annotations throughout the dependency injection pipeline.
- Nullable composition arguments (
.Arg<T?>()) and root arguments (.RootArg<T?>()) no longer generate null checks, allowingnullvalues to flow through as intended. - Non-null bindings can satisfy nullable dependencies — useful for optional constructor parameters, nullable factory results, and nullable collection elements.
- Type system integration: nullable annotations are preserved when reading contracts, building graphs, and generating composition members.
- Generic constraint awareness: prefer
where T : class?overwhere T : classfor contracts with nullable generic arguments to avoid C# compiler warnings. - New warnings for ambiguous nullable root types in
Resolvemethods help catch potential issues early. - See
readme/nullable-reference-types.mdfor detailed examples and best practices.
- Nullable composition arguments (
-
TryBuildUp for Builders
- New
TryBuildUpmethod generated alongsideBuildUpfor safe type-based composition. - Returns
falseinstead of throwing when the runtime subtype is unknown, enabling graceful fallback handling. - Example:
composition.TryBuildUp(externalRobot)returnsfalsefor unsupported types whilecomposition.BuildUp(externalRobot)would throwArgumentException. - See
readme/builders.mdfor usage examples.
- New
👥 Contributors
Thanks to everyone who contributed to this release:
- Adam Hathcock (@adamhathcock)
- Nikolay Pianikov (@NikolayPianikov)
Full Changelog: 2.3.7...2.4.0
2.3.7
🚀 New Features
-
Generate Interfaces from Classes — special thanks to Adam Hathcock for designing and implementing this feature! 🎉
- New
[GenerateInterface]attribute lets a concrete service produce a matching interface automatically, so consumers can depend on the abstraction without hand-writing it. - Customize the generated interface: set the interface name, namespace, and access level via named arguments.
- Generate several interfaces from one class by applying
[GenerateInterface]multiple times, with per-interface member selection. - Ignore specific members with
[IgnoreInterface], which takes precedence over[GenerateInterface]. - Generic interfaces are supported.
- XML documentation comments on source members are preserved on the generated interface.
- New
-
Scope Setup
- New
SetupScopemethod for composing scoped sub-graphs from a parent composition — open a scope per request/operation, share scoped instances inside it, and dispose them at the end. - Scopes can be produced by factory methods, enabling custom scope creation logic.
- Parent and child scopes are validated to be distinct, preventing accidental self-nesting.
- New
Hint.ScopeMethodNamehint lets you rename the generated scope factory method to fit your domain (e.g.SetupScope,CreateScope,BeginRequest):DI.Setup() .Hint(Hint.ScopeMethodName, "SetupScope") .Bind().As(Scoped).To<RequestContext>();
- New
-
Unity Scene Scopes
- New Unity scene scopes scenario: each loaded Unity scene gets its own scope, so scoped services are shared within a scene and isolated between scenes — Unity creates the
MonoBehaviourinstances and Pure.DI builds them up.
- New Unity scene scopes scenario: each loaded Unity scene gets its own scope, so scoped services are shared within a scene and isolated between scenes — Unity creates the
-
Microsoft DI Integration: Scoped Lifetimes
IServiceProviderintegration now supports scoped lifetimes end-to-end viacomposition.CreateScope(), matchingMicrosoft.Extensions.DependencyInjectionsemantics.- Tag-based resolution and value-type roots are supported through the integration.
-
Generated Code is Marked
- All generated code is now decorated with
[GeneratedCode], so analyzers, coverage, and code-style tools can recognize and skip it correctly. - The generated
Compositionclass embeds the actual Pure.DI package version it was produced with, instead of a hard-coded string.
- All generated code is now decorated with
🐛 Bug Fixes
- Fixed scoped/singleton instance propagation through nested scopes.
- Fixed read-only handling of setup-context arguments inside generated scope methods.
👥 Contributors
Thanks to everyone who contributed to this release:
- Adam Hathcock (@adamhathcock)
- Nikolay Pianikov (@NikolayPianikov)
Full Changelog: 2.3.6...2.3.7
2.3.6
🚀 New Features
-
BCL Dictionary Support
- Added support for injecting .NET Base Class Library
Dictionary<TKey, TValue>types - Extended injection capabilities to cover standard dictionary types from BCL
- Added support for injecting .NET Base Class Library
-
IContext Extensions
- Added RootName and RootType properties to
IContextinterface - Added IsLockRequired property to
IContext
- Added RootName and RootType properties to
-
Extended Factory Method Bindings
- Added support for up to 16-parameter factory method bindings
- Increased from previous limit, supporting more complex factory scenarios
⚡ Performance Improvements
-
Metadata Analysis
- Optimized metadata analysis pipeline
- Reduced overhead in setup metadata detection
-
Code Generation
- Optimized factory code generation with reduced allocations
- Optimized type resolution process
-
Graph Building
- Reduced semantic analysis overhead by favoring syntactic analysis
- Improved graph construction performance
📝 Documentation
- Updated and improved README documentation
- Added "Article Basics" documentation
Full Changelog: 2.3.5...2.3.6
2.3.5
🐛 Bug Fixes
- #140 Incorrect generated code for the PerBlock lifetime: a local or parameter named ... cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
- #141 Objects created without explicit binding began to use the specified default lifetime instead of Transient
Contributors
@YoshihiroIto
@NikolayPianikov
Full Changelog: 2.3.4...2.3.5