microsoft / microsoft/microsoft-ui-reactor
AOT compatibility: review and address remaining limitations
- Dominant language
- C#
- Stars
- 646
- Forks
- 54
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 84
Description
## Summary
PR #69 enabled \IsAotCompatible=true\ across the repo, migrated JSON serialization to source-generated contexts, and suppressed all trimming/AOT warnings. The core rendering path is AOT-safe and the stress_perf projects already publish AOT successfully.
However, several features rely on reflection that the .NET trimmer would strip under \PublishAot=true\. These are currently annotated with \[UnconditionalSuppressMessage]\ — they compile clean but would fail at runtime in an AOT-published app.
## Hard Blocker (upstream)
### TreeView collection binding
- **Impact**: \IList\ ↔ \IVector\ marshalling fails under AOT
- **Root cause**: CsWinRT generates different marshalling stubs when \PublishAot=true\
- **Reproduction**: Publish \AppTests.Host\ with AOT, run \ControlUpdate_Collections\ selftest (\CollUpdate_TVPresent\ check fails)
- **Status**: Upstream CsWinRT/WinAppSDK bug — not fixable on our side
- **Action**: Track upstream fix; revisit when CsWinRT ships a fix
## Reflection-dependent features
These features use \Type.GetProperty()\, \Activator.CreateInstance\, or generic \JsonSerializer\ calls that the trimmer can't statically analyze.
### PropertyGrid / TypeRegistry
- **Files**: \TypeRegistry.cs\, \ReflectionTypeMetadataProvider.cs\, \ArrayOperations.cs\
- **What breaks**: Property discovery, editor resolution, array manipulation via \Activator.CreateInstance\
- **Possible fix**: Source generator that emits \TypeMetadata\ at compile time instead of reflecting at runtime
### DataGrid AutoColumns
- **Files**: \ColumnDsl.cs\, \DataGridState.cs\, \DataGridComponent.cs\
- **What breaks**: \AutoColumns()\ reflects on \T\ to infer columns
- **Possible fix**: \[DynamicallyAccessedMembers]\ on \T\ already preserves members for callers who use concrete types; source-gen for full AOT
### Devtools (all tools)
- **Files**: \DevtoolsFireTool.cs\, \DevtoolsPropertyTools.cs\, \DevtoolsStateTool.cs\, \McpDispatcher.cs\
- **What breaks**: State inspector, property editor, fire tool — all use heavy reflection (assembly scanning, \GetMethod()\, \GetField()\)
- **Possible fix**: Devtools could be excluded from AOT builds entirely via \#if\ or feature switches, since they're debug-only tooling
### ObservableTreeTracker
- **Files**: \ObservableTreeTracker.cs\
- **What breaks**: Deep INPC change tracking — reflects to discover nested \INotifyPropertyChanged\ properties
- **Possible fix**: Source generator that emits property metadata for observable model types
### Navigation state persistence
- **Files**: \NavigationHandle.cs\
- **What breaks**: \GetState()\ / \SetState()\ use generic \JsonSerializer.Serialize\ without a source-gen context
- **Possible fix**: Require callers to pass \JsonTypeInfo\ or register types on a shared \JsonSerializerContext\
### IntlAccessor (localization)
- **Files**: \IntlAccessor.cs\
- **What breaks**: \ToArgsDictionary\ reflects over anonymous type properties for localization format args
- **Possible fix**: Accept \IDictionary\ directly instead of anonymous objects, or use source-gen
### RenderContext.SnapshotHooks
- **Files**: \RenderContext.cs\
- **What breaks**: Devtools hook inspection — reflects into generic \HookState.Value\ fields
- **Possible fix**: Exclude from AOT builds (devtools-only feature)
### ReactorComponentTypeConverter
- **Files**: \ReactorApp.cs\
- **What breaks**: XAML type conversion via \Type.GetMethod()\, \Activator.CreateInstance\
- **Possible fix**: Source generator for known component types
### WebViewCssMeasurement
- **Files**: \WebViewCssMeasurement.cs\
- **What breaks**: JSON serialization of CSS measurement results without source-gen context
- **Possible fix**: Add types to a \JsonSerializerContext\
## What works under AOT today
- Core rendering / reconciliation
- Layout (Yoga / FlexPanel)
- All built-in controls (except TreeView collection binding)
- Charting
- Accessibility scanning (source-gen JSON)
- MCP server protocol (source-gen JSON)
- All 6 stress_perf variants (Direct, Bound, Reactor, ReactorGrid, DirectX, WPF)
## Recommended approach
1. **Short term**: Ship \IsAotCompatible=true\ as-is (PR #69). The suppressions document known reflection sites without breaking existing JIT workflows.
2. **Medium term**: Add feature switches (\RuntimeFeature.IsDynamicCodeSupported\) to gate devtools and other debug-only reflection behind runtime checks.
3. **Long term**: Invest in source generators for PropertyGrid, ObservableTreeTracker, and DataGrid AutoColumns to make them fully AOT-compatible.
Contributor guide
Assessment
This issue has not been assessed yet.