You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Developers can safely trim their apps which use Dependency Injection to reduce the size of their apps #44432
Source Generators are a new technology that was added to Roslyn in the .NET 5 timeframe, but we have not yet utilized them by creating generators to assist with runtime and framework features. We will work to define customer scenarios in more detail here with customer development.
Code that uses runtime reflection and reflection.emit causes issues for Trimming and Native AOT. Source generators can be used to generate alternative code at build time that is static so can be used in conjunction with Trimming and AOT. Work on trimming ASP.NET apps has revealed where there are current limitations that can be solved by source generators.
This item tracks creating a Source Generator for Dependency Injection (DI).
Reacted by dymo, Kevin Miller, Shreyas Jejurkar, Yusuf Tarık Günaydın, Kyle Wascher, Kylar182, GazziFX, MartyIX, NN, Amr and 13 more
Reacted by Angelo Belchior, Marvin Rühe, Pent Ploompuu, Shreyas Jejurkar, Curtis Buys, Yusuf Tarık Günaydın, Kylar182, MartyIX, Joseph Petersen, Shubham Ranjan and 2 more
Reacted by Daniel Cazzulino, Mourad CHIBANE, Mahmoud Ali, Angelo Belchior, NumAniCloud, Rogier van der Hee, Thibaut Dambacher, Ryouko Konpaku, Dmitry Stratiychuk, Shreyas Jejurkar and 8 more
@danroth27 how important is DI to Blazor scenarios? I suspect this story would be expensive, so I'd like to understand whether it's particularly valuable. @glennc My understanding is that this is mainly about startup of ASP.NET apps, so it would not be P0 for this release.
DI is used heavily in both Blazor and ASP.NET Core.
@danroth27 - But how important is it to have a Source Generator for DI for Blazor? We are able to use DI in a Blazor WASM app just fine in 5.0 without a Source Generator. Is one critical for 6.0 scenarios?
Note: For Blazor WASM, we currently use a "Reflection" provider for DI since RuntimeFeature.IsDynamicCodeCompiled is false on Blazor WASM:
For Blazor WebAssembly, our goal is to get significantly better runtime performance with AoT compilation to WebAssembly, but while also hitting our download size targets. I don't know for sure if this work is needed to hit those requirements, but I think it makes sense to assume it's not until we have data that shows otherwise.
Note that the title of this issue is no longer a problem. With #55102 and #79425, Microsoft.Extensions.DependencyInjection can be used safely with trimmed and NativeAOT applications.
Do we want to leave this issue open to explicitly track creating a source generator for DI? If so, I think we should update the title.
In this code, the WindowsServiceLifetime service is only injected if the current process is a Windows Service process. This cannot be checked at compile time. Or if it was, you would need to compile for both Windows Services and non-Windows Services and then decide which assemblies to publish. If there are more than a couple of these, the combination of compilation targets gets unwieldly.
The order the services are added to the service collection is important. For non-enumerable services, the last one added is the one that gets resolved. Ordering is hard to express at compile-time.
Given (2) above, in order for the source generator to know which service to use, it needs to know the entire closure of the services registered. This can only be done at the "app level" - the only place where the whole closure can be known. However, there are many service implementations that are not public types. For example:
Here you can see hostBuilderContext is created at runtime with some settings, and then passed to services.AddSingleton(hostBuilderContext);. Again, this is not possible to accomplish at compile-time.
Reacted by David Fowler, Pavel Krymets and Dan Vicarel
Closing this issue. I don't believe we will add support for a source generated DI system given the issues outlined in #44432 (comment). https://github.com/pakrym/jab is available for anyone who wants to use a source generated DI system in their application.
As of .NET 8, developers can use Dependency Injection in both trimmed and native AOT'd apps safely. The only "gotcha" is using value types in open generic services described in #79286. This was addressed by #79425.
@eerhardt how does that work with built-in DI registration extensions though.... entire mechanisms such as IOptions and HttpClient registration extensions would not be compatible with that. Nor would any library that uses the MEDI registration syntax... say stuff like AddAzureClients from Microsoft.Extensions.Azure, or all the OTEL methods from OpenTelemetry.Extensions.Hosting. You suggest that library as an alternative but to me it really is not an alternative if it just cannot work at all with existing well-defined patterns.
I'm sad to hear Microsoft won't attempt anything native in this regard, especially considering how the team has been prioritizing performance so much in the past years. Optimizing the standard DI mechanism would go a long way considering how pervasive it is.
@julealgon - See the issues outlined in #44432 (comment). Your questions are pointing to exactly why this isn't possible with a source generator (at least how they exist today), and thus why I closed this issue.
why this isn't possible with a source generator (at least how they exist today)
@eerhardt You say this, but there was a lot of custom work to allow minimal API to be source generated behind the scenes to support AOT while keeping the exact same runtime method calls in place/same signatures. Surely some of that work could be applied to DI and keep the same DI registration interface intact?
Did that use the experimental interceptors capability?
My point was that Microsoft would be better equipped to "do something about it" vs a vendor library that cannot enhance the underlying framework to support new things. My hope was that, if you kept this open, there would be at least a chance that Microsoft would look into alternative ways, be them use of interceptors, or improvements to source generators, to make it work, like they did for minimal API.
See #82679 (comment). The current model is incompatible with source generators. Minimal APIs is much easier in comparison and we were able to make it work. We would need to design a new system that was statically analyzable to make this work.
See #82679 (comment). The current model is incompatible with source generators. Minimal APIs is much easier in comparison and we were able to make it work. We would need to design a new system that was statically analyzable to make this work.
Fair enough. Thanks for sharing that interesting comment David. I know you were directly involved in the Minimal API AOT work so I'll take your word for it that this is much harder to achieve.
Activity
Dotnet-GitSync-Bot commentedon Nov 9, 2020
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
samsp-msft commentedon Nov 9, 2020
Refactored from #43545
danmoseley commentedon Nov 9, 2020
@danroth27 how important is DI to Blazor scenarios? I suspect this story would be expensive, so I'd like to understand whether it's particularly valuable.
@glennc My understanding is that this is mainly about startup of ASP.NET apps, so it would not be P0 for this release.
cc @marek-safar
danroth27 commentedon Nov 9, 2020
@danmosemsft DI is used heavily in both Blazor and ASP.NET Core.
eerhardt commentedon Nov 10, 2020
@danroth27 - But how important is it to have a Source Generator for DI for Blazor? We are able to use DI in a Blazor WASM app just fine in 5.0 without a Source Generator. Is one critical for 6.0 scenarios?
Note: For Blazor WASM, we currently use a "Reflection" provider for DI since
RuntimeFeature.IsDynamicCodeCompiledisfalseon Blazor WASM:runtime/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceCollectionContainerBuilderExtensions.cs
Lines 66 to 74 in 7b93881
ericstj commentedon Nov 10, 2020
@davidfowl was mentioning that this was important to investigate in 6.0 but not "do".
danroth27 commentedon Nov 10, 2020
For Blazor WebAssembly, our goal is to get significantly better runtime performance with AoT compilation to WebAssembly, but while also hitting our download size targets. I don't know for sure if this work is needed to hit those requirements, but I think it makes sense to assume it's not until we have data that shows otherwise.
danmoseley commentedon Nov 10, 2020
That sounds like Priority:2 (moderately important) until we have data otherwise?
28 remaining items
danmoseley commentedon Mar 28, 2022
leaving open for future
eerhardt commentedon Jan 30, 2023
Note that the title of this issue is no longer a problem. With #55102 and #79425, Microsoft.Extensions.DependencyInjection can be used safely with trimmed and NativeAOT applications.
Do we want to leave this issue open to explicitly track creating a source generator for DI? If so, I think we should update the title.
eerhardt commentedon Jan 30, 2023
Jotting down my thoughts on why making a source generator for DI is hard.
runtime/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/src/WindowsServiceLifetimeHostBuilderExtensions.cs
Lines 99 to 116 in a342915
In this code, the
WindowsServiceLifetimeservice is only injected if the current process is a Windows Service process. This cannot be checked at compile time. Or if it was, you would need to compile for both Windows Services and non-Windows Services and then decide which assemblies to publish. If there are more than a couple of these, the combination of compilation targets gets unwieldly.The order the services are added to the service collection is important. For non-enumerable services, the last one added is the one that gets resolved. Ordering is hard to express at compile-time.
Given (2) above, in order for the source generator to know which service to use, it needs to know the entire closure of the services registered. This can only be done at the "app level" - the only place where the whole closure can be known. However, there are many service implementations that are not public types. For example:
runtime/src/libraries/Microsoft.Extensions.Options/src/OptionsServiceCollectionExtensions.cs
Line 26 in a342915
runtime/src/libraries/Microsoft.Extensions.Options/src/UnnamedOptionsManager.cs
Line 9 in a342915
It isn't possible for a source generator in the application to reference internal types in libraries it references.
runtime/src/libraries/Microsoft.Extensions.Hosting/src/HostApplicationBuilder.cs
Lines 121 to 135 in a342915
runtime/src/libraries/Microsoft.Extensions.Hosting/src/HostBuilder.cs
Lines 293 to 305 in a342915
Here you can see
hostBuilderContextis created at runtime with some settings, and then passed toservices.AddSingleton(hostBuilderContext);. Again, this is not possible to accomplish at compile-time.mairaw commentedon May 26, 2023
I'm cleaning up the .NET 6 project. This shows as completed on the project dashboard but still open here. Not sure if this needs any updates.
eerhardt commentedon Aug 30, 2024
Closing this issue. I don't believe we will add support for a source generated DI system given the issues outlined in #44432 (comment). https://github.com/pakrym/jab is available for anyone who wants to use a source generated DI system in their application.
As of .NET 8, developers can use Dependency Injection in both trimmed and native AOT'd apps safely. The only "gotcha" is using value types in open generic services described in #79286. This was addressed by #79425.
julealgon commentedon Aug 30, 2024
@eerhardt how does that work with built-in DI registration extensions though.... entire mechanisms such as
IOptionsandHttpClientregistration extensions would not be compatible with that. Nor would any library that uses the MEDI registration syntax... say stuff likeAddAzureClientsfromMicrosoft.Extensions.Azure, or all the OTEL methods fromOpenTelemetry.Extensions.Hosting. You suggest that library as an alternative but to me it really is not an alternative if it just cannot work at all with existing well-defined patterns.I'm sad to hear Microsoft won't attempt anything native in this regard, especially considering how the team has been prioritizing performance so much in the past years. Optimizing the standard DI mechanism would go a long way considering how pervasive it is.
eerhardt commentedon Aug 30, 2024
@julealgon - See the issues outlined in #44432 (comment). Your questions are pointing to exactly why this isn't possible with a source generator (at least how they exist today), and thus why I closed this issue.
julealgon commentedon Aug 30, 2024
@eerhardt You say this, but there was a lot of custom work to allow minimal API to be source generated behind the scenes to support AOT while keeping the exact same runtime method calls in place/same signatures. Surely some of that work could be applied to DI and keep the same DI registration interface intact?
Did that use the experimental interceptors capability?
My point was that Microsoft would be better equipped to "do something about it" vs a vendor library that cannot enhance the underlying framework to support new things. My hope was that, if you kept this open, there would be at least a chance that Microsoft would look into alternative ways, be them use of interceptors, or improvements to source generators, to make it work, like they did for minimal API.
davidfowl commentedon Aug 30, 2024
See #82679 (comment). The current model is incompatible with source generators. Minimal APIs is much easier in comparison and we were able to make it work. We would need to design a new system that was statically analyzable to make this work.
julealgon commentedon Aug 30, 2024
@davidfowl
Fair enough. Thanks for sharing that interesting comment David. I know you were directly involved in the Minimal API AOT work so I'll take your word for it that this is much harder to achieve.