8000 HybridCache : simplify AOT usage with default JSON serialization by mgravell · Pull Request #6475 · dotnet/extensions · GitHub
[go: up one dir, main page]

Skip to content

HybridCache : simplify AOT usage with default JSON serialization #6475

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

mgravell
Copy link
Member
@mgravell mgravell commented May 21, 2025
  1. don't touch JsonSerializerOptions.Default in AOT mode
  2. add new extension methods to register JsonSerializerOptions (these are convenience methods on an existing registration pattern)
  3. offer a suitable runtime error message instead, if no JSON options supplied in AOT mode
  4. include [UnconditionalSuppressMessage] to prevent build-time consumer warnings

This has been tested successfully with an AOT published project; it now works correctly at runtime with zero build-time warnings, test code shown below; without the WithJsonSerializerOptions line, exception at runtime:

When using AOT, JsonSerializerOptions with TypeInfoResolver specified must be provided via IHybridCacheBuilder.WithJsonSerializerOptions.

Without this work, it is not obvious how to register AOT JSON options, and the consumer must use <NoWarn>$(NoWarn);IL2026;IL2104;IL3053</NoWarn> or similar to get a clean build, which is too wide.

open questions:

  • API naming: With* or Add* ?
  • which API review process should this follow?

Sample:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Caching.Hybrid;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();
var jsonOptions = new JsonSerializerOptions() { TypeInfoResolver = Bar.MyJsonSerializationContext.Default };
services.AddHybridCache().WithJsonSerializerOptions(jsonOptions);
services.AddStackExchangeRedisCache(options => options.Configuration = "localhost:6379");
using var provider = services.BuildServiceProvider();

var cache = provider.GetRequiredService<HybridCache>();

int id = 42;
var obj = await cache.GetOrCreateAsync($"/ob/{id}", ct => GetTheThingAsync(id));
Console.WriteLine(obj.Id);

static ValueTask<Bar.Foo> GetTheThingAsync(int id) => new(new Bar.Foo(id));

namespace Bar
{
    [JsonSourceGenerationOptions(WriteIndented = true)]
    [JsonSerializable(typeof(Foo))]
    internal partial class MyJsonSerializationContext : JsonSerializerContext
    {
    }

    internal sealed class Foo(int id)
    {
        public int Id => id;
    }
}
Microsoft Reviewers: Open in CodeFlow

2. add new extension methods to register JsonSerializerOptions
3. offer a suitable error message instead, if none supplied in AOT mode

open question: naming: With* or Add* ?
@mgravell
Copy link
Member Author
mgravell commented May 21, 2025

CI build fail is because of API delta:

error LA0003: (NETCORE_ENGINEERING_TELEMETRY=Build) Newly added symbol 'Microsoft.Extensions.DependencyInjection.HybridCacheBuilderExtensions.WithJsonSerializerOptions(Microsoft.Extensions.Caching.Hybrid.IHybridCacheBuilder, System.Text.Json.JsonSerializerOptions)' must be marked as experimental

This in in turn tied into the open "which API review process should this follow?" question; however, I'll add the attribute for now

@mgravell mgravell requested a review from a team as a code owner May 21, 2025 11:18
@eerhardt
Copy link
Member

This should be able to resolve Microsoft.Extensions.Caching.Hybrid is not trim/AOT compatible (dotnet/extensions#5624).

@eerhardt
Copy link
Member

We should remove

<!-- https://github.com/dotnet/extensions/issues/5624 -->
<LibraryProjects Remove="$(RepoRoot)\src\Libraries\Microsoft.Extensions.Caching.Hybrid\Microsoft.Extensions.Caching.Hybrid.csproj" />

as well. We should make the library trimming and AOT compatible.

Comment on lines 24 to +28
</PropertyGroup>

<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</IsAotCompatible>

You only need to set IsAotCompatible. It will default IsTrimmable. See https://github.com/dotnet/sdk/blob/fd301ec19c3190b8129b28847d6faed9d26bc0d3/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L24

< 8000 /div>
Comment on lines +15 to +17
[UnconditionalSuppressMessage("AOT", "IL2026", Justification = "Checked at runtime, guidance issued")]
[UnconditionalSuppressMessage("AOT", "IL2070", Justification = "Checked at runtime, guidance issued")]
[UnconditionalSuppressMessage("AOT", "IL3050", Justification = "Checked at runtime, guidance issued")]
Copy link
Member
@eerhardt eerhardt May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be moved even more local to only suppress around the lines of code that need it. Doing it the current way will suppress it for all new code written in this class, which isn't correct.

Also, is there a better Justifcation that can be written here? A little more of a reason why this is OK.

See

for some examples.

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

Successfully merging this pull request may close these issues.

2 participants
0