-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove RequiresDynamicCode from Microsoft.Extensions.DependencyInjection #79286
Comments
Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection Issue DetailsIn .NET 7, with #73829, we annotated Microsoft.Extensions.DependencyInjection as RequiresDynamicCode because it supports enumerable and generic servcies with ValueTypes. When using DI with ValuesTypes, the array and generic code might not be available. In .NET 8 we need a better approach in order to support applications that use DependencyInjection and publish for NativeAOT. DependencyInjection needs to have reliable behavior before and after publishing for NativeAOT. The application can't work successfully at development-time, but then fail after publishing with ProblemThe good thing, there are only limited scenarios where DependencyInjection needs to use dynamic code. And these scenarios are not used very often in real-world applications.
ProposalThe proposed approach is similar to how we solved trim-compatibility with DependencyInjection in #55102. We will resolve the 2 NativeAOT warnings above by adding a runtime check that is behind a new AppContext switch 'Microsoft.Extensions.DependencyInjection.VerifyAotCompatibility'. The runtime check ensures the Types being used with Enumerable and Open Generic services are only Reference Types. If an application tries to create an Enumerable or Closed Generic service of a ValueType, DependencyInjection will throw an exception. The check is enabled by default when PublishAot=true. The recommendation for applications that want to publish for NativeAOT is to put cc @davidfowl @halter73 @JamesNK @MichalStrehovsky @agocke @vitek-karas @jkotas
|
Please don't break other AOT scenarios |
We're trying to make AOT scenarios work, not break them 😄 |
I definitely don't intend to break existing AOT scenarios. For iOS and Android, I don't believe they are currently using the But if they are, and need this functionality turned off, they will be able to disable this property by default, even when |
We don't set If we ever want to have this property mean something else than Native AOT, adjusting this feature flag would be just one of the many other things in the SDK that need adjusting. Right now PublishAot means "publish with the limitations (and optimization opportunities) that apply to Native AOT" and it doesn't have a mapping to a mode of the Mono runtime. It could in the future. |
For platforms running Mono, runtime/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in Line 57 in 41ae1ae
I don't know of anything Mono-related that uses |
Yep, that's my understanding too. |
For iOS, tvOS and partially Mac Catalyst, AOT is on by default, and tweaked/turned off (kind of) with
Might I suggest |
The impact is not limited to native AOT. The patterns flagged by these checks are going to be slow on platforms without a JIT, like iOS, etc. |
@eerhardt as a datapoint I've used dependency injection as a simple extensibility mechanism where I'm injecting an IEnumerable into a service where there has been multiple T's also injected into the DI infra: Example:Registration: https://github.com/Azure/azure-sdk-tools/blob/28c8db9782063964505d875bbc9d161baf930ab1/tools/pipeline-witness/Azure.Sdk.Tools.PipelineWitness/Startup.cs#L71 I'd want to make sure IEnumerable injection for reference types would still work. From your issue description it wasn't entirely clear whether you saw this as a valid scenario. |
@davidfowl has informed me that IEnumerable where T is a reference type would be supported. |
Correct - reference types are still 100% supported. From the proposal above:
|
We need a better approach in order to support applications that use DependencyInjection and publish for NativeAOT. DependencyInjection needs to have reliable behavior before and after publishing for NativeAOT. The application can't work successfully at development-time, but then fail after publishing with PublishAot=true. We will resolve the 2 NativeAOT warnings above by adding a runtime check that is behind a new AppContext switch Microsoft.Extensions.DependencyInjection.VerifyAotCompatibility. The runtime check ensures the Types being used with Enumerable and Open Generic services are only Reference Types. If an application tries to create an Enumerable or Closed Generic service of a ValueType, DependencyInjection will throw an exception. The check is enabled by default when PublishAot=true. Fix dotnet#79286
I have changed the proposal to be based off the DynamicCodeSupport feature switch instead of adding one specific for DependencyInjection. |
…ion (#79425) * Remove RequiresDynamicCode from Microsoft.Extensions.DependencyInjection We need a better approach in order to support applications that use DependencyInjection and publish for NativeAOT. DependencyInjection needs to have reliable behavior before and after publishing for NativeAOT. The application can't work successfully at development-time, but then fail after publishing with PublishAot=true. We will resolve the 2 NativeAOT warnings above by adding a runtime check that is behind the new AppContext switch added in #80246 (`System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported`). The runtime check ensures the Types being used with Enumerable and Open Generic services are only Reference Types. If an application tries to create an Enumerable or Closed Generic service of a ValueType, DependencyInjection will throw an exception. The check is enabled by default when PublishAot=true. Fix #79286
I've been considering contributing to the DI library. It seems to me a like a code generator would be a good solution for this. It may require people modify their code in how they define their DI. But I'm curious, is anyone currently considering/working on this? |
|
With the current pattern, a code generator doesn't work well because you can't generate "efficient" code unless you have the full closure of dependencies at compile time. That isn't possible today because the service collection is a runtime list of dependencies which makes this sort of code generation hard. We're don't have plans to re-design how dependencies are registered (like jab does), at least not as part of the core container implementation. |
In .NET 7, with #73829, we annotated Microsoft.Extensions.DependencyInjection as RequiresDynamicCode because it supports enumerable and generic servcies with ValueTypes. When using DI with ValuesTypes, the array and generic code might not be available.
In .NET 8 we need a better approach in order to support applications that use DependencyInjection and publish for NativeAOT. DependencyInjection needs to have reliable behavior before and after publishing for NativeAOT. The application can't work successfully at development-time, but then fail after publishing with
PublishAot=true
.Problem
The good thing, there are only limited scenarios where DependencyInjection needs to use dynamic code. And these scenarios are not used very often in real-world applications.
Proposal
The proposed approach is similar to how we solved trim-compatibility with DependencyInjection in #55102.
We will resolve the 2 NativeAOT warnings above by adding a runtime check that is behind a new AppContext switch
Microsoft.Extensions.DependencyInjection.VerifyAotCompatibility
. The runtime check ensures the Types being used with Enumerable and Open Generic services are only Reference Types. If an application tries to create an Enumerable or Closed Generic service of a ValueType, DependencyInjection will throw an exception. The check is enabled by default whenPublishAot=true
.The recommendation for applications that want to publish for NativeAOT is to put
<PublishAot>true</PublishAot>
in their .csproj. That way they get the appropriate analyzers and runtime behaviors during development-time, i.e. F5 in VS ordotnet run
from the command line. Applications using the incompatible features above will be broken at development time if the app is intended to be published for AOT. This will give the app developer indication their application won't work after publishing for NativeAOT as well.cc @davidfowl @halter73 @JamesNK @MichalStrehovsky @agocke @vitek-karas @jkotas
The text was updated successfully, but these errors were encountered: