Annotate Serialization/Serializer.cs reflective surface for AOT (closes #70)#74
Merged
Merged
Conversation
#70) First Polecat AOT-pillar slice (polecat#70), mirroring the methodology that closed JasperFx slices #252-#255 + the tail in JasperFx#260. ISerializer interface annotated ToJson(object) — [RUC] + [RDC] FromJson<T>(string|Stream|DbDataReader) — [RUC] + [RDC] FromJson(Type, string|Stream|DbDataReader) — [RUC] + [RDC] FromJsonAsync<T>(Stream, CancellationToken) — [RUC] + [RDC] FromJsonAsync(Type, Stream, CancellationToken) — [RUC] + [RDC] Interface XML docs updated with the AOT story: AOT-publishing apps should supply a custom ISerializer implementation backed by a System.Text.Json source-generator JsonSerializerContext rather than the reflection-based default. Serializer impl Matching [RequiresUnreferencedCode] + [RequiresDynamicCode] on every override (required to keep IL2046 quiet). Suppressed with justification ApplyEnumStorage — IL3050 on JsonStringEnumConverter (non-generic enum converter; AOT consumers use the generic JsonStringEnumConverter<TEnum>) ApplyNonPublicMembers — IL2026 + IL3050 + IL2075 on DefaultJsonTypeInfoResolver + fallback GetProperties scan. The NonPublicMembers feature is reflection-driven by intent; opting into it is opt-in to reflection. Effect on the punch list (per TFM) Serializer.cs slice: 36 → 0 (closed) Polecat total: 270 → 422 (+152 cascade) The +152 cascade is honest propagation, not regression. With the un-annotated Serializer, every caller hid behind it; now the trim-impact surface is explicit at the call sites. The cascade lands in files already targeted by other AOT-pillar issues: DocumentStore.ProjectionReplay.cs — covered by polecat#71 Linq/PolecatQueryableExtensions.cs / LinqQueryProvider.cs — covered by polecat#72 Storage/DocumentMapping.cs + DocumentProviderRegistry — covered by polecat#73 Plus some new cascade in transitive callers (Patching/PatchExpression.cs, Events/EventOperations.cs, Internal/QuerySession.cs, Internal/DocumentProvider.cs) that will be absorbed into a future Polecat tail-cleanup PR mirroring JasperFx#260. Verification Polecat.csproj + Polecat.Tests.csproj build clean (0 errors) Closes #70.
This was referenced May 13, 2026
jeremydmiller
added a commit
that referenced
this pull request
May 13, 2026
Two updates to keep the migration-guide accurate as the 2026-wave alphas roll forward: - Bump the foundation-pin table to current Polecat 4 alpha versions: JasperFx alpha.8 → alpha.11, JasperFx.Events alpha.3 → alpha.4, Weasel.* alpha.2 → alpha.3. Note that the alpha line is still rolling forward and consumers should pin all five together. - Rewrite the AOT / codegen posture section to reflect the actual landed state: IsAotCompatible=true is set on the Polecat assembly (#67), and the reflective surfaces have been progressively annotated through #74 (serialization), #75 (projection replay), #76 (LINQ extension/provider), and #77 (storage / registry / event-store explorer). Link out to the cross-stack "Publishing AOT with JasperFx" guide on jasperfx.github.io for the end-to-end walkthrough. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
jeremydmiller
added a commit
that referenced
this pull request
May 13, 2026
Fifth slice in Polecat's AOT-pillar (jasperfx#213) cleanup, following the Serializer (#74), ProjectionReplay (#75), LINQ (#76), and Storage/Registry (#77) slices that have landed on main. The patching subsystem reflects on the document's property expressions to build JSON path strings and feeds the resulting patch values through ISerializer.ToJson when emitting JSON_MODIFY() SQL. JsonPathHelper also compiles small Expression.Lambda delegates to evaluate constant sub- expressions during path resolution. Document types T flow in from Schema.For<T>() / IDocumentSession.Patch<T>() at the registration boundary and are preserved per the AOT publishing guide; AOT consumers supply a source-generator-backed ISerializer impl. Apply class-level [UnconditionalSuppressMessage] with justifications: - Patching/PatchExpression<T>: IL2026/IL3050 (ISerializer.ToJson on patch values) - Patching/PatchOperation: IL2026/IL3050 (ISerializer.ToJson when building JSON_MODIFY commands) - Patching/JsonPathHelper: IL3050 (Expression.Lambda for constant sub-expression evaluation) 194 → 152 unique IL warnings (-42) in Polecat.csproj. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
First Polecat AOT-pillar slice (closes #70), mirroring the methodology that closed JasperFx slices #252-#255 + the tail in JasperFx/jasperfx#260.
ISerializer interface annotated
ToJson(object)[RequiresUnreferencedCode]+[RequiresDynamicCode]FromJson<T>(string | Stream | DbDataReader)(×3)[RUC]+[RDC]FromJson(Type, string | Stream | DbDataReader)(×3)[RUC]+[RDC]FromJsonAsync<T>(Stream, CancellationToken)[RUC]+[RDC]FromJsonAsync(Type, Stream, CancellationToken)[RUC]+[RDC]XML docs updated with the AOT story: AOT-publishing apps should supply a custom
ISerializerimplementation backed by a System.Text.Json source-generatorJsonSerializerContextrather than the reflection-based default.Serializer impl
Matching
[RequiresUnreferencedCode]+[RequiresDynamicCode]on every override (required to keep IL2046 quiet across the impl boundary).Suppressed with justification
ApplyEnumStorageJsonStringEnumConverter(JsonNamingPolicy, bool). The non-generic enum converter requires runtime code gen; AOT consumers use the genericJsonStringEnumConverter<TEnum>.ApplyNonPublicMembersDefaultJsonTypeInfoResolver+ the fallbackGetPropertiesscan. The NonPublicMembers feature is reflection-driven by intent; opting in is opting into reflection.Effect on the punch list
The +152 cascade is honest propagation, not regression. With the un-annotated Serializer, every caller hid behind it; now the trim-impact surface is explicit at the call sites. The cascade lands in files already targeted by other AOT-pillar issues:
DocumentStore.ProjectionReplay.cs— covered by AOT pillar: annotate DocumentStore.ProjectionReplay.cs reflective surface #71Linq/PolecatQueryableExtensions.cs/LinqQueryProvider.cs— covered by AOT pillar: annotate Linq subsystem reflective surface #72Storage/DocumentMapping.cs+DocumentProviderRegistry— covered by AOT pillar: annotate Storage + DocumentProvider registry + EventStore explorer reflective surface #73Plus new cascade in transitive callers (
Patching/PatchExpression.cs,Events/EventOperations.cs,Internal/QuerySession.cs,Internal/DocumentProvider.cs) that will be absorbed into a future Polecat tail-cleanup PR mirroring JasperFx#260.Verification
Polecat.csproj+Polecat.Tests.csprojbuild clean (0 errors)Closes #70.
🤖 Generated with Claude Code