Remove all the store resolvers and mark all the assemblies as trimming/Native AOT-compatible#2278
Merged
kevinchalet merged 1 commit intoopeniddict:devfrom Mar 22, 2025
Merged
Conversation
…g/Native AOT-compatible
This was referenced Mar 23, 2025
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1346.
This PR introduces trimming and Native AOT support for all the OpenIddict stacks: while there are still rough edges that make using Native AOT in real world applications quite complicated in practice (e.g I haven't been able to make EF Core 9 work on Native AOT and it doesn't seem ASP.NET Core Identity supports it yet), it has incredible advantages - like massively reduced startup times or reduced memory footprint - that make it a highly desirable option for some scenarios. Using Native AOT is also required in some cases (e.g modernized UWP applications converted to .NET 9.0 and published to the Microsoft Store), so it is essential that OpenIddict be compatible with it.
While making the OpenIddict client, server and validation stacks trimming and AOT-compatible didn't require any complicated change (beyond moving to source-generated JSON serialization), the core stack needed a lot more attention due the store resolver model not being trimming/AOT-friendly at all (it uses reflection in a way that can't be analyzed statically).
The following changes were required to make OpenIddict AOT-friendly:
IOpenIddict*StoreResolver) and all their implementations have been removed and the managers have been updated to now directly take anIOpenIddict*Store<T>argument instead of anIOpenIddict*StoreResolver.OpenIddictCoreOptions.Default*Typeoptions (e.gDefaultApplicationType) have been removed and the untyped managers (IOpenIddict*Manager) no longer use options to determine the actual entity type at runtime. Instead, each store integration is now responsible for replacing theIOpenIddict*Managerservices with a service descriptor pointing to the genericOpenIddict*Manager<T>implementation with the correctTargument: by default, the default entity types provided by the store are used, but the managers can be re-registered with a different type when the user decides to use different models (e.g viaoptions.UseEntityFrameworkCore().ReplaceDefaultModels<...>()).OpenIddictCoreBuilderhave been removed: while they were very powerful and easy-to-use (e.g theReplace*Managermethods supported both open and closed generic types and were able to determine the entity type from the base type definition), they weren't AOT-compatible.Replace*Store()andReplace*Manager()APIs have been introduced inOpenIddictCoreBuilder. TheReplace*Manager()have two overloads that can be used depending on whether you need to register a closed or open generic type:TContextgeneric argument from the definition. Similarly, the MongoDB C# driver isn't AOT (or even trimming) compatible yet, but the stores have been updated to ensure we only use statically-analyzable patterns.IOpenIddictEntityFrameworkCoreContextinterface containing a singleValueTask<DbContext> GetDbContextAsync(CancellationToken cancellationToken)method (similar to what's currently used in the MongoDB integration) has been introduced to allow each to resolve theDbContextto use. A default implementation namedOpenIddictEntityFrameworkCoreContext<TContext>is used by theOpenIddictEntityFrameworkCoreBuilder.UseDbContext<TContext>()API to resolve theTContexttype specified by the user.OpenIddictEntityFrameworkCoreBuilder.ReplaceDefaultEntities<...>API has been preserved - including the overload accepting a singleTKeyparameter but no longer use options internally. Instead, they re-register the untypedIOpenIddict*Managerto point to the correctOpenIddict*Manager<T>instances depending on the generic types set by the user.The changes introduced in the core are quite massive but shouldn't impact most users. Library or framework authors on the other hand (e.g ABP Framework, Orchard Core or Squidex) are much more likely to be affected. I'll work with these partners in the next few weeks to ensure these changes didn't break any scenario.
Note: I haven't tested the OpenIddict server and validation stacks in AOTed ASP.NET Core apps yet, but the results seen with the OpenIddict client and its system integration in a console application (with the token storage feature disabled, since EF Core 9 doesn't work well currently) are really promising: it's able to launch an interactive authorization flow in the blink of an eye, even on extremely modest hardware! 🎉