-
Reuse immutable snapshot keys for empty, exact-only and generic-definition-only GetAllServices discovery, avoiding per-call union sets while preserving eager typed aggregation, key deduplication and native service lifetimes #93.
-
Use a reverse descriptor scan for collection lifetime queries, eliminating intermediate arrays while preserving last matching registration, assignable service types and keyed value equality #92.
-
Cache constructor and parameter metadata with weak type keys and remove temporary selection/map-search allocations from DependsOn activation. Preserve resolution-time constructor availability, named overrides, keyed lookup and optional defaults #84.
-
Restore native constructor graph validation for decorated implementation-type originals, rejecting invalid nested/generic/enumerable/cyclic graphs before dependency factories execute. Preserve original keys, independent registration caches and exactly-once disposal; keep scoped caching correct after native compilation #121.
-
Preserve native metadata order when FromKeyedServices and ServiceKey share a constructor parameter. Keep named DependsOn overrides first, respect effective null/inherited keys, and apply the same binding in selection and resolution without additional service lookups #122.
-
Restore original type activation through decorators when a provider exposes ordinary availability probing and keyed resolution without a keyed availability probe. Require keyed probing only for non-null dependency lookup keys, while preserving native constructor rules, generic constraint checks, layer lifetimes and disposal ownership #120.
-
Honor ServiceKey injection only for non-null keyed contexts in DependsOn activation. Preserve ordinary registered services, null factory results and optional defaults for unkeyed/null-key parameters, while retaining named override priority and non-null key type validation #112.
-
Preserve native constructor selection for decorated original type registrations, including ignored preferred-constructor attributes, parameter-type-set ambiguity, contextual keys, generic constraints and native-provider metadata probing, while retaining factory/map activation policies, layer lifetimes and disposal ownership #111.
-
Preserve registered factory null results in mapped and contextual keyed constructor dependencies, including named key maps and decoration. Apply optional defaults only to missing registrations while retaining missing-required failures and original factory exceptions #110.
-
Keep keyed decorator inner binding separate from ServiceKey and FromKeyedServices parameters, preserving explicit, inherited and null-key dependency lookup independently of parameter order, repeated layers, native lifetimes and disposal ownership #109.
-
Check explicit registrations for keyed built-in constructor dependencies instead of treating native DI's implicit unkeyed services as available under every key. Preserve native-provider support, optional defaults, named and inherited keys, and explicit or AnyKey registrations without activating rejected dependencies #108.
-
Recognize native AnyKey open-generic fallback during DependsOn and contextual keyed constructor selection, including named key maps and inherited-key decoration, while preserving concrete-key resolution, registration precedence, optional defaults and generic-constraint errors without activating rejected dependencies #107.
-
Normalize optional DateTime metadata on .NET Framework in mapped activation and keyed decoration, preserving named/registered overrides and unused constructor selection while sharing native-compatible defaults with diagnostic activation #106.
-
Require
ValidateOnBuild = truewhen transient-disposable diagnostics are enabled. Unsupported combinations throwArgumentExceptionduring provider creation; native validation rejects constructor cycles and other invalid closed type registrations at startup, including unused registrations. Factory and open-generic validation retain native limits #89. -
Open-generic startup warnings now use the root
ILoggerFactoryrather than a directly registeredILogger<ServiceProviderFactory>. Configure standard logging (for example,AddLogging) to receive them. Warning-delivery failures no longer fail provider creation; warnings are best-effort #90. -
Raise
Microsoft.Extensions.DependencyInjectionto a minimum of 10.0.0, including the upstream keyed enumerable/open-generic cache identity fix (dotnet/runtime#113343, #46). Raise its requiredMicrosoft.Bcl.AsyncInterfacesdependency to 10.0.0. Consumers pinning DI 8.x/9.x must upgrade; all existing library target frameworks remain supported.
-
Preserve original constructor exception identity and stack traces in
DependsOnactivation by sharing reflection-wrapper unwrapping with contextual keyed activation, while leaving dependency-resolution exceptions unchanged #83. -
Restore typed resolution in
GetAllServices<T>()for value-type services such asint, preserving explicit enumerable registrations, snapshot-backed key merging, AnyKey exclusion and private decorator filtering #85. -
Preserve exact public-service diagnostic exclusions through every private decorator layer, including repeated keyed decoration, while retaining unrelated dependency checks and container disposal ownership #91.
-
Normalize optional nullable-enum defaults in mapped activation and contextual keyed decorators, preserving null defaults, named overrides and registered-service precedence #82.
-
Skip incompatible open-generic implementations in ordinary assembly scans before configuration, preventing invalid marker/interface descriptors while preserving closed implementations and native open-generic self type registrations #87.
-
Keep fallback
ServiceKeys<T>metadata empty without activating unrelated applicationobjectservices or creating scoped-to-singleton dependencies, while preserving mutable compatibility collections and snapshot-backed discovery #86. -
Remove the temporary startup-warning scope and return the provider even when optional warning delivery fails, preserving ownership of logging dependencies until provider disposal and avoiding forced synchronous disposal of async-only scoped loggers #90.
-
Preserve native DI constructor preference and parameter-type ambiguity rules when transient-disposable diagnostics instrument ordinary type registrations, including keyed context, optional defaults, null factory results and disposal ownership #88.
-
Build provider metadata on a private collection copy so repeated or failed builds leave caller registrations unchanged, avoid accumulating support services, and keep each provider's discovery and compatibility metadata independent #64.
-
Decorate the last registration occurrence when the same ServiceDescriptor instance is added more than once, preserving keyed and unkeyed registration order, repeated decorator layers, lifetimes and disposal ownership #63.
-
Preserve implementation-specific rejection messages for unkeyed open-generic transient disposable registrations, including IDisposable and IAsyncDisposable implementations #62.
-
Stop local package builds immediately after a failed native command and preserve its exit code, preventing stale-output packaging after failed validation #61.
-
Apply precise System namespace boundaries and the exact mscorlib assembly name when selecting framework interfaces, preserving application contracts from Systematic assemblies and excluding IAsyncDisposable consistently across runtimes #60.
-
Update the private SourceLink build dependency to 10.0.401, resolving patched Microsoft.Build.Tasks.Git for CVE-2026-62900 #65.
-
Preserve native ValidateOnBuild graph validation when transient-disposable diagnostics are enabled, without activating user services during validation #59.
-
Isolate transient-disposable diagnostic resolution frames across execution-context branches, preserving inherited ancestry and nested exception cleanup #58.
-
Use the active descriptor lifetime for diagnostic singleton exemptions when duplicate registrations have different lifetimes, preserving last-registration-wins metadata queries #57.
-
Retain root disposal ownership of rejected transient factory results in diagnostic mode, including async-only disposables, without recapturing results already owned by the root #56.
-
Preserve native explicit IEnumerable registrations in GetAllServices, including instance/factory precedence and keyed mixtures, while retaining private decorator filtering and AnyKey exclusion #55.
-
Exclude the AnyKey sentinel from GetAllServices per-key enumeration, avoiding duplicate concrete results and transient activations while preserving wildcard metadata, fallback resolution and registration multiplicity #54.
-
Respect namespace boundaries and exact global-namespace selection in AssemblyInspector; explicitly include all namespaces when children of the global namespace are requested #53.
-
Use value equality for collection key-only registration queries, matching typed helpers for boxed values, equal strings and custom keys #52.
-
Preserve ServiceKey injection and inherited/explicit/null dependency lookup through keyed decorators, diagnostics and DependsOn activation, retaining named overrides and disposal ownership #51.
-
Preserve actual requested keys and per-key inner lifetime caches through AnyKey decorator layers, retaining container disposal ownership #50.
-
Consolidate transient-disposable exception formatting across target frameworks #24. Formattable service keys now use invariant culture in the netstandard2.0 library as well as modern targets; preserve message layout, keyed resolution-stack order and factory markers.
-
Isolate provider registration, lifetime and key-discovery metadata from external mutation. Preserve public mutable metadata types as compatibility copies while provider helpers and diagnostics use a private snapshot #28.
-
Preserve container disposal ownership of decorated factory/type services and intermediate decorators, without disposing caller-owned instances or colliding with implementation registrations #37.
-
Support keyed open-generic provider startup and merge closed/generic-definition keys for all-service discovery and registration/lifetime queries #38.
-
Keep keyed and unkeyed provider lifetime queries independent, including singleton exemptions in transient-disposable diagnostics #39.
-
Select a satisfiable DependsOn constructor at resolution time, honor preferred constructors, reject ambiguity, and support optional defaults without constructing rejected dependencies #23.
- Refresh consumer guidance for current provider guarantees and add the portable
mammoth-diAgent Skill with validated application recipes and agent-specific discovery instructions.
IServiceCollectionlifetime check methods (IsTransientServiceRegistered,IsScopedServiceRegistered,IsSingletonServiceRegistered, and their keyed variants) now returnfalseinstead of throwingInvalidOperationExceptionwhen the service is not registered.- Fixed
ResolutionContextstack corruption inPatchForResolutionContextTrackingwhen a factory delegate throws an exception. Push/Pop calls are now wrapped intry/finallyfor all 4 registration paths (non-keyed/keyed × factory/type). - Fixed bidirectional
IsAssignableFromcheck inGetServiceDescriptorsmethod that incorrectly returned unrelated base-type registrations #19.- The method now uses unidirectional matching:
serviceType == serviceDescriptor.ServiceType || serviceType.IsAssignableFrom(serviceDescriptor.ServiceType). - This fixes incorrect lifetime checks in methods like
IsTransientServiceRegistered,IsSingletonServiceRegistered, etc., which depend on.Last()to select the correct registration.
- The method now uses unidirectional matching:
- Fixed missing
returnstatements inTryAdd*overload methods with emptyDependsOnarray, which caused unnecessary reflection calls and potential double-registration attempts #18.
- Decorators: removed reflection-based proxy creation (
Reflection.Emit) and allow class decoration #11.- The
Decorate<TService, TDecorator>method now supports decorating services registered by concrete class, not just interfaces. - Factory-registered services can be decorated without generating dynamic proxy interfaces at runtime.
- The
- Added net10.0 support.
- Updated .net assemblies dependencies to 9.0.0.
- AssemblyInspector does not allow for proper filter composition #13
- added support for .NET 8.0 and .NET 9.0 (previously only netstandard2.0 was supported).
- ServiceProviderFactory / IsRegistered support: Registering a KeyedService with an object key results in System.ArgumentException: Object must be of type String #9
- Improved detection of incorrect usage of transient disposable object: InvalidOperationException has more information about the service being resolved (like a resolution context stack, if available).
- Improved detection of incorrect usage of transient disposable object: added an exclusion pattern list for services that should not be checked (like some AspNetCore internal services).
ServiceProviderFactory: added a constructor that acceptsExtendedServiceProviderOptionsto be used in Host Builder initialization like:Host.CreateDefaultBuilder(args).UseServiceProviderFactory(new ServiceProviderFactory(new ExtendedServiceProviderOptions()))
ServiceProviderFactory.CreateServiceProvider()now returnServiceProviderinstead ofIServiceProvider.
- Improved detection of incorrect usage of transient disposable objects:
- Log warning when a transient disposable open generic service is registered.
- Improved detection of incorrect usage of transient disposable objects:
- Fixed a bug for keyed service descriptors.
- Now correctly identifies the resolution for all but open generics.
- Open generic resolution context cannot be tracked! They will NOT result in errors if they are disposable and registered as transient when resolved by the root scope.
- Added a new option to throw an exception when an open generic transient disposable service is registered (we cannot track open generics, better to use all closed types to avoid memory leaks).
- Removed
ResolutionContextTrackingServiceProviderDecoratorfrom compilation (it was bugged and only tracked the root object instead of the entire resolution chain). The implementation file is kept for reference. Resolution context tracking is now implemented with new service decorators that "wrap" the original code and replace the original ones (similar to how the detection of incorrect usage of transient disposables works).
- Improved Incorrect Usage of Transient Disposables: we optionally allow Singleton Objects to create Transient Disposable services #7.
- Detect Incorrect Usage of Transient Disposables services: resolving a transient disposable result in a memory leak #5.
- Added ServiceProvider extension methods to check if Registered Services are: Transient, Scoped, Singleton #1
IServiceCollectionextension methods behavior changes:IsTransientServiceRegistered: looks for non-keyed services only.IsScopedServiceRegistered: looks for non-keyed services only.IsSingletonServiceRegistered: looks for non-keyed services only.- Added
IsKeyedTransientServiceRegistered,IsKeyedScopedServiceRegistered,IsKeyedSingletonServiceRegisteredto check for keyed services.
- Improved NuGet package (deterministic, source link).
- Added net9.0 tests.
- AssemblyInspector: added Configure() method #2.
-
Namespace changed for the following classes:
Dependency-> fromMammoth.Extensions.DependencyInjectiontoMammoth.Extensions.DependencyInjection.ConfigurationParameter-> fromMammoth.Extensions.DependencyInjectiontoMammoth.Extensions.DependencyInjection.Configuration
-
AssemblyInspector lifestyle selectors signature changed; it does not accept "dependsOn" anymore, use the new Configure() method instead:
var descriptors = new AssemblyInspector() .FromAssemblyContaining<TestService>() .BasedOn(typeof(TestService)) .WithServiceBase() .LifestyleTransient(dependsOn: new Dependency[] { Parameter.ForKey("param").Eq("nonexisting") });
becomes:
var descriptors = new AssemblyInspector() .FromAssemblyContaining<TestService>() .BasedOn(typeof(TestService)) .WithServiceBase() .Configure(cfg => cfg.DependsOn = new Dependency[] { Parameter.ForKey("param").Eq("nonexisting") }) .LifestyleTransient();
- Fixed namespaces.
- NuGet Package and GitHub Actions (build, test, publish)
Initial Release
- Decorator: support registering decorator pattern.
- DependsOn: register specific dependencies for constructor parameters.
- Registration Checks: allows to check if a service was registered in ServiceCollection and ServiceProvider
- AssemblyInspector: allows to inspect assemblies for types and register them easily.