refactor(serialization): unify default object activation - #11390
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The implementation preserves constructor-selection semantics and comprehensively tests exception identity across supported activation paths.
Review effort: Balanced
Findings: None
What changed in this PR
Unifies default serializer activation across JIT and NativeAOT runtimes.
Changes:
- Centralizes constructor selection, activation, and exception unwrapping.
- Expands managed and NativeAOT exception-preservation coverage.
- Updates activation documentation.
| File | Description |
|---|---|
src/Orleans.Serialization/Activators/DefaultActivator.cs |
Implements unified activation. |
test/Orleans.Serialization.UnitTests/DefaultActivatorTests.cs |
Expands managed tests. |
test/Orleans.NativeAotSmoke/Activation.cs |
Expands NativeAOT smoke coverage. |
docs/site/src/content/docs/implementation/serialization.md |
Documents unified behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Code coverage
Report-only conclusion: current-main baseline stale. The newest successful coverage run tested 6bf11ad, not current main 9bb744a. Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities. The comparison remains report-only while normal line and branch variance is calibrated. Coverage details |
Problem
#11369 introduced separate default object activation paths: an emitted constructor delegate on JIT runtimes and generic construction on NativeAOT. Both paths implement the same constructor-selection and exception contract.
Solution
Move creation into the common
DefaultActivator<T>implementation. Cache whetherThas a public parameterless constructor, invoke it usingActivator.CreateInstance<T>(), and allocate an uninitialized object for constructor-bypass types. The existing reference/value activator types continue to provide the constrained registration surfaces.Normalize the single runtime-generated
TargetInvocationExceptionwrapper usingExceptionDispatchInfo. Constructor failures retain their original identity, inner exception, and stack trace, including constructor-thrownTargetInvocationExceptionvalues with or without an inner exception. Extend the existing managed tests and centralized native Activation smoke scenario to complete that exception matrix, and update the implementation documentation.Rationale
CoreCLR's generic activation implementation in .NET 8 and .NET 10, and .NET 10 NativeAOT's generic construction intrinsic, wrap constructor failures once. This guarantee supports the same exception normalization across runtimes while each runtime supplies its constructor and allocator implementation.
The shared path favors implementation consistency over the emitted delegate's microoptimization. Public APIs, constructor-preservation annotations, and supported target frameworks remain unchanged. NativeAOT coverage targets .NET 10; managed compatibility retains .NET 8.
Microsoft Reviewers: Open in CodeFlow