Skip to content

fix!: close open generic registrations for injected properties and hook parameters - #229

Merged
vbreuss merged 1 commit into
mainfrom
fix/open-generic-property-closings
Oct 30, 2026
Merged

vbreuss merged 1 commit into
mainfrom
fix/open-generic-property-closings

Conversation

@vbreuss

@vbreuss vbreuss commented Oct 30, 2026

Copy link
Copy Markdown
Member

An injected property that needed a closing only an open generic registration provides was reported as AWT101, although the service is effectively registered: moving the same dependency into the constructor made it work. Expansion was seeded only from constructor and factory parameters, which pushed users to change their domain types instead of declaring the injection on the container (goal 7). Lifecycle hook parameters had the same gap.

Open generic expansion now also seeds from the injected members of every container-constructed implementation ([Inject] properties, [InjectProperty] entries and [InjectProperty(typeof(...))] entries, an open-generic target applied per closing) and from the parameters of the OnActivated/OnRelease hook a registration dispatches. Collection elements and relationship shapes are unwrapped like constructor parameters, a keyed member expands the keyed closing, and the existing constraint check (AWT126), depth and count limits (AWT129) and the rule that a dropped overridable default does not seed all apply unchanged. The [InjectProperty] entries are now read before registration collection so expansion can see them, and hook overload selection is shared with expansion so only the dispatched hook seeds.

BREAKING CHANGE: an Optional injected property whose service only an open generic registration can provide is now filled with that closing, as a constructor parameter would be, instead of being left at its default. A collection-typed injected property likewise now contains the closings of matching open registrations instead of being empty.

…ok parameters

An injected property that needed a closing only an open generic registration provides was reported as AWT101, although the service is effectively registered: moving the same dependency into the constructor made it work. Expansion was seeded only from constructor and factory parameters, which pushed users to change their domain types instead of declaring the injection on the container (goal 7). Lifecycle hook parameters had the same gap.

Open generic expansion now also seeds from the injected members of every container-constructed implementation ([Inject] properties, [InjectProperty<T>] entries and [InjectProperty(typeof(...))] entries, an open-generic target applied per closing) and from the parameters of the OnActivated/OnRelease hook a registration dispatches. Collection elements and relationship shapes are unwrapped like constructor parameters, a keyed member expands the keyed closing, and the existing constraint check (AWT126), depth and count limits (AWT129) and the rule that a dropped overridable default does not seed all apply unchanged. The [InjectProperty] entries are now read before registration collection so expansion can see them, and hook overload selection is shared with expansion so only the dispatched hook seeds.

BREAKING CHANGE: an Optional injected property whose service only an open generic registration can provide is now filled with that closing, as a constructor parameter would be, instead of being left at its default. A collection-typed injected property likewise now contains the closings of matching open registrations instead of being empty.
@vbreuss vbreuss self-assigned this Oct 30, 2026
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown

Test Results

   27 files  ± 0     27 suites  ±0   1h 52m 46s ⏱️ + 56m 26s
1 704 tests +14  1 704 ✅ +14  0 💤 ±0  0 ❌ ±0 
8 255 runs  +70  8 255 ✅ +70  0 💤 ±0  0 ❌ ±0 

Results for commit 0e47de9. ± Comparison against base commit 2cd4104.

@github-actions

Copy link
Copy Markdown

🚀 Benchmark Results

Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 7763 3.23GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Realistic Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 251.7 ns 3.70 ns 3.46 ns 0.96 568 B 1.00
Awaiten 262.6 ns 3.30 ns 3.08 ns 1.00 568 B 1.00
MsDI 620.7 ns 15.49 ns 14.49 ns 2.36 1104 B 1.94
Autofac 6,836.7 ns 68.65 ns 57.33 ns 26.04 10784 B 18.99
Jab 180.2 ns 4.29 ns 4.02 ns 0.69 432 B 0.76
DryIoc 405.6 ns 9.44 ns 8.83 ns 1.54 944 B 1.66
SimpleInjector 831.6 ns 8.89 ns 8.32 ns 3.17 1096 B 1.93
PureDI 179.3 ns 4.83 ns 4.52 ns 0.68 632 B 1.11
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 7763 2.65GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Resolve Size Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 8 5.875 ns 0.1548 ns 0.1448 ns 0.82 - NA
Awaiten 8 7.158 ns 0.0075 ns 0.0066 ns 1.00 - NA
MsDI 8 7.791 ns 0.2418 ns 0.2262 ns 1.09 - NA
Autofac 8 124.992 ns 0.9249 ns 0.8199 ns 17.46 656 B NA
Jab 8 2.724 ns 0.0801 ns 0.0749 ns 0.38 - NA
PureDI 8 5.427 ns 0.0056 ns 0.0049 ns 0.76 - NA
DryIoc 8 9.068 ns 0.0100 ns 0.0089 ns 1.27 - NA
SimpleInjector 8 11.067 ns 0.0071 ns 0.0055 ns 1.55 - NA
baseline* 256 6.283 ns 0.0068 ns 0.0061 ns 0.77 - NA
Awaiten 256 8.129 ns 0.0099 ns 0.0088 ns 1.00 - NA
MsDI 256 7.745 ns 0.1907 ns 0.1691 ns 0.95 - NA
Autofac 256 127.790 ns 4.4808 ns 4.1913 ns 15.72 656 B NA
Jab 256 42.682 ns 0.0290 ns 0.0226 ns 5.25 - NA
PureDI 256 7.334 ns 0.0057 ns 0.0050 ns 0.90 - NA
DryIoc 256 9.088 ns 0.0883 ns 0.0826 ns 1.12 - NA
SimpleInjector 256 14.452 ns 0.0230 ns 0.0215 ns 1.78 - NA
Details

BenchmarkDotNet v0.15.8, Linux Ubuntu 26.04.1 LTS (Resolute Raccoon)
AMD EPYC 7763 2.63GHz, 1 CPU, 4 logical and 2 physical cores
.NET SDK 10.0.303
[Host] : .NET 10.0.14 (10.0.14, 10.0.1426.52326), X64 RyuJIT x86-64-v3

Job=InProcess Toolchain=InProcessEmitToolchain IterationCount=15
LaunchCount=1 WarmupCount=10

Build Size Mean Error StdDev Ratio Allocated Alloc Ratio
baseline* 8 20.923 ns 0.8159 ns 0.7233 ns 0.83 208 B 1.00
Awaiten 8 25.08 ns 0.716 ns 0.598 ns 1.00 208 B 1.00
MsDI 8 1,654.52 ns 20.534 ns 18.203 ns 66.00 5688 B 27.35
Autofac 8 31,740.66 ns 126.971 ns 112.556 ns 1,266.19 32478 B 156.14
Jab 8 13.73 ns 0.702 ns 0.657 ns 0.55 96 B 0.46
PureDI 8 18.43 ns 0.307 ns 0.287 ns 0.74 128 B 0.62
DryIoc 8 733.78 ns 3.146 ns 2.627 ns 29.27 1528 B 7.35
SimpleInjector 8 13,480.87 ns 106.994 ns 94.847 ns 537.77 24760 B 119.04
baseline* 256 161.892 ns 9.0341 ns 8.4505 ns 0.71 4176 B 1.00
Awaiten 256 227.65 ns 9.938 ns 9.296 ns 1.00 4176 B 1.00
MsDI 256 16,117.61 ns 364.810 ns 341.243 ns 70.91 61016 B 14.61
Autofac 256 777,065.38 ns 6,735.426 ns 6,300.322 ns 3,418.74 736562 B 176.38
Jab 256 98.39 ns 5.950 ns 5.566 ns 0.43 2080 B 0.50
PureDI 256 114.59 ns 3.969 ns 3.713 ns 0.50 2112 B 0.51
DryIoc 256 46,593.47 ns 209.895 ns 196.336 ns 204.99 80734 B 19.33
SimpleInjector 256 408,809.52 ns 2,747.519 ns 2,435.604 ns 1,798.58 572981 B 137.21

baseline* rows show the corresponding Awaiten benchmark from the most recent successful main branch build with results, for regression comparison.

@vbreuss
vbreuss merged commit af214cd into main Oct 30, 2026
16 checks passed
@vbreuss
vbreuss deleted the fix/open-generic-property-closings branch October 30, 2026 17:18
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
…for injected properties and hook parameters (#229) by Valentin Breuß
github-actions Bot added a commit that referenced this pull request Oct 30, 2026
…for injected properties and hook parameters (#229) by Valentin Breuß
@github-actions

Copy link
Copy Markdown

This is addressed in release v0.8.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant