Skip to content

feat: generator-emitted DTO constructor lambdas for IL trimming#50

Merged
keithdv merged 3 commits intomainfrom
feat/generator-dto-trimming
Mar 26, 2026
Merged

feat: generator-emitted DTO constructor lambdas for IL trimming#50
keithdv merged 3 commits intomainfrom
feat/generator-dto-trimming

Conversation

@keithdv
Copy link
Copy Markdown
Contributor

@keithdv keithdv commented Mar 26, 2026

Summary

  • Source generator discovers plain DTO return types from factory method signatures and emits DtoConstructorRegistry.Register<T>(() => new T()) calls
  • [DynamicallyAccessedMembers(All)] on Register<T> preserves the entire type from IL trimming
  • NeatooJsonTypeInfoResolver uses the registry instead of Activator.CreateInstance (which fails under trimming)
  • Fixes DTO deserialization in trimmed Blazor WASM apps where IsTrimmable=true on domain assemblies causes DefaultJsonTypeInfoResolver's reflection-based discovery to fail

Closes #48

Why this is needed

Normal Blazor WASM apps don't hit this because their assemblies aren't trimmed (TrimMode=partial only trims IsTrimmable=true assemblies). RemoteFactory intentionally marks domain assemblies trimmable to remove server-only business logic from the client — a core value proposition. This means DefaultJsonTypeInfoResolver's reflection breaks for plain DTOs.

Verified

Test plan

  • All unit tests pass (490 x2 frameworks)
  • All integration tests pass (502 x2 frameworks)
  • All Design tests pass (42 x2 frameworks)
  • Manual: trimmed Blazor WASM DTO deserialization works (collection + single item)
  • Records not affected (ExampleRecordResult excluded from registry)
  • Neatoo types not affected (still use DI-based CreateObject)

🤖 Generated with Claude Code

keithdv and others added 3 commits March 25, 2026 22:30
The source generator now discovers plain DTO return types from factory
method signatures and emits DtoConstructorRegistry.Register<T>(() => new T())
calls with [DynamicallyAccessedMembers(All)] to preserve the type from
IL trimming. NeatooJsonTypeInfoResolver uses the registry instead of
Activator.CreateInstance, which fails under trimming.

This fixes DTO deserialization in trimmed Blazor WASM apps where
IsTrimmable=true causes DefaultJsonTypeInfoResolver's reflection-based
constructor/property discovery to fail.

Also fixes Design.Client.Blazor index.html script tag placeholder.

Closes #48

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Explains why IsTrimmable=true breaks DefaultJsonTypeInfoResolver for
plain DTOs and how the generator automatically preserves them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@keithdv keithdv merged commit 48b9569 into main Mar 26, 2026
2 checks passed
@keithdv keithdv deleted the feat/generator-dto-trimming branch March 26, 2026 03:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NeatooJsonSerializer breaks under Blazor WASM IL trimming for non-Neatoo DTOs

1 participant