| | | 1 | | using System.Text.Json.Serialization.Metadata; |
| | | 2 | | |
| | | 3 | | namespace AsyncResponse; |
| | | 4 | | |
| | | 5 | | /// <summary> |
| | | 6 | | /// Opt-in extensibility for resolving JSON contract metadata for the payload types AsyncResponse |
| | | 7 | | /// serializes on the application's behalf: response payloads inside envelopes, durable-flow inputs, |
| | | 8 | | /// step results and flow values, and literal callback arguments. By default these resolve through |
| | | 9 | | /// the runtime's reflection-based resolver, so apps that serialize with reflection today need to |
| | | 10 | | /// register nothing. Trimmed and Native AOT apps run without that resolver |
| | | 11 | | /// (<c>JsonSerializer.IsReflectionEnabledByDefault</c> is <c>false</c>), so they must register a |
| | | 12 | | /// source-generated <see cref="System.Text.Json.Serialization.JsonSerializerContext"/> covering |
| | | 13 | | /// their payload types at startup: |
| | | 14 | | /// <code> |
| | | 15 | | /// AsyncResponseJsonSerialization.RegisterResolver(MyAppJsonContext.Default); |
| | | 16 | | /// </code> |
| | | 17 | | /// <para> |
| | | 18 | | /// This is process-wide and additive, mirroring <see cref="AsyncResponseTypeResolution"/>: |
| | | 19 | | /// registered resolvers are consulted for types the library's own wire-type metadata does not |
| | | 20 | | /// cover, in registration order, before the reflection fallback. Register at startup, before the |
| | | 21 | | /// host begins waiting on responses — metadata is cached per type on first use. |
| | | 22 | | /// </para> |
| | | 23 | | /// </summary> |
| | | 24 | | public static class AsyncResponseJsonSerialization |
| | | 25 | | { |
| | 3 | 26 | | private static volatile IJsonTypeInfoResolver[] _resolvers = []; |
| | 3 | 27 | | private static readonly object _gate = new(); |
| | | 28 | | |
| | | 29 | | /// <summary> |
| | | 30 | | /// Registers a metadata resolver — typically a source-generated |
| | | 31 | | /// <see cref="System.Text.Json.Serialization.JsonSerializerContext"/> — consulted when |
| | | 32 | | /// serializing or deserializing application payload types. |
| | | 33 | | /// </summary> |
| | | 34 | | public static void RegisterResolver(IJsonTypeInfoResolver resolver) |
| | | 35 | | { |
| | 3 | 36 | | ArgumentNullException.ThrowIfNull(resolver); |
| | 3 | 37 | | lock (_gate) |
| | | 38 | | { |
| | 3 | 39 | | _resolvers = [.. _resolvers, resolver]; |
| | 3 | 40 | | } |
| | 3 | 41 | | } |
| | | 42 | | |
| | | 43 | | /// <summary>Snapshot of the registered resolvers, in registration order.</summary> |
| | 3 | 44 | | internal static IJsonTypeInfoResolver[] Resolvers => _resolvers; |
| | | 45 | | |
| | | 46 | | /// <summary>Clears all registered resolvers. Test seam only.</summary> |
| | | 47 | | internal static void Reset() |
| | | 48 | | { |
| | 3 | 49 | | lock (_gate) |
| | | 50 | | { |
| | 2 | 51 | | _resolvers = []; |
| | 2 | 52 | | } |
| | 2 | 53 | | } |
| | | 54 | | } |