Skip to content

feat(codegen): register static grain-reference factories - #11386

Draft
ReubenBond wants to merge 6 commits into
dotnet:mainfrom
ReubenBond:rb-generated-grain-reference-factories
Draft

ReubenBond wants to merge 6 commits into
dotnet:mainfrom
ReubenBond:rb-generated-grain-reference-factories

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Warning

Incomplete approach: automatic reflection-free construction covers only non-generic grain references. Generic proxies have generated Create methods, but this PR does not automatically generate or register factories for closed generic grain interfaces. Without explicit closed registrations, generic reference construction still uses MakeGenericType, constructor lookup, and ConstructorInvoker.

The NativeAOT generic scenarios work because the tests manually register their closed proxy factories. They do not demonstrate automatic generic support. This falls short of replacing reflective construction for all grain references. This PR is draft, is not ready to merge, and will likely not be merged.

Follow-up to #11371.

Generated grain references use statically registered, typed factory delegates. RpcProvider resolves them by the explicitly declared grain interface, avoiding interface guessing, constructor reflection, emitted IL, and grain-key boxing on the registered construction path. The existing activator continues to share runtime state, interface versions, invocation options, and serialization services while each reference retains its own key.

Proxy bases declare their construction contract with [GenerateProxyFactory(typeof(TDelegate))]. The generator reads the delegate's argument types, passing modes, and result type, emits a static Create method with a direct constructor call, and registers the method group in InterfaceProxyFactoryOptions<TDelegate>. GrainReference declares the named GrainReferenceFactory delegate, which accepts shared runtime state and a grain key and returns a grain reference. The base annotation, registrations, cached activators, and legacy compatibility delegates all use that same named type. Factory generation and metadata registration remain independent of grain-specific types.

Factory declarations are inherited, and a nearer proxy base can override the declaration. Closed delegates and supported argument passing modes are validated at build time; factory results use identity or implicit reference conversions to preserve the constructed proxy instance. C# checks constructor calls for both non-generic and open generic proxies. Unannotated RPC bases retain their existing type-only registration behavior. A public read-only registration view lets other proxy consumers invoke their own typed factories. Coverage includes non-grain factories with multiple arguments, generic proxy families, inheritance/overrides, custom delegates with ref, in, and out arguments, and rejection of user-defined result conversions.

Factories for non-generic interfaces are registered automatically. Closed-generic NativeAOT construction uses explicitly supplied concrete factory registrations; open mappings support runtime-selected arguments on JIT through reflective generic closure. Older generated binaries and custom proxies registered by type retain the constructor-invoker compatibility path. Legacy custom overrides and replacement typed factories preserve their precedence. The earlier grain-specific root attribute, discovery models, and capability checks are removed.

The existing production grain-reference NativeAOT scenario exercises generated non-generic references, manually registered value/reference-type generic proxies, and a non-grain proxy whose factory comes solely from its base declaration. Generated proxy names remain implementation details. Public API surfaces are regenerated and architecture guidance describes factory contracts, registration, and compatibility boundaries.

Microsoft Reviewers: Open in CodeFlow

Copilot AI balanced review requested due to automatic review settings October 2, 2026 03:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Nested generic interfaces can produce invalid generated code, and duplicate manifest registrations can unexpectedly discard static factories.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity

Open (2)
What changed in this PR

Adds statically generated grain-reference factories to avoid reflective construction, particularly under NativeAOT.

Changes:

  • Generates direct typed factory registrations, including closed generic interfaces.
  • Resolves factories by declared interface while retaining legacy proxy compatibility.
  • Adds runtime, code-generation, NativeAOT, API, and documentation coverage.
File Description
test/​Orleans.NativeAotSmoke/​GrainReferences.cs Tests closed generic factories under NativeAOT.
test/​Orleans.Core.Tests/​GrainReferences/​ReferenceConstructionFixture.cs Extends the reference-construction fixture.
test/​Orleans.Core.Tests/​GrainReferences/​GrainReferenceActivatorTests.cs Covers factory resolution and compatibility.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestGrainWithMultipleInterfaces.verified.cs Updates generated factory snapshot.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestGrainWithDifferentKeyTypes.verified.cs Updates key-type factory snapshots.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestGrainMethodAnnotatedWithResponseTimeout.verified.cs Updates generated factory snapshot.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestGrainMethodAnnotatedWithInvokableBaseType.verified.cs Updates generated factory snapshot.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestGrainComplexGrain.verified.cs Updates generated factory snapshot.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestClassWithGenerateMethodSerializersAnnotation.verified.cs Updates generated factory snapshot.
test/​Orleans.CodeGenerator.Tests/​snapshots/​OrleansSourceGeneratorTests.TestBasicGrain.verified.cs Updates generated factory snapshot.
test/​Orleans.CodeGenerator.Tests/​GrainReferenceFactoryCodegenTests.cs Tests factory code generation and diagnostics.
src/​Orleans.Serialization/​Configuration/​TypeManifestOptions.cs Adds typed manifest extension storage.
src/​Orleans.Core/​GrainReferences/​GrainReferenceActivator.cs Resolves and invokes registered factories.
src/​Orleans.Core.Abstractions/​Configuration/​GrainReferenceFactoryOptions.cs Defines factory registration options.
src/​Orleans.Core.Abstractions/​CodeGeneration/​GenerateGrainReferenceAttribute.cs Adds closed-interface generation attribute.
src/​Orleans.CodeGenerator/​Model/​ReferenceAssemblyModelExtractor.cs Extracts requested closed factories.
src/​Orleans.CodeGenerator/​Model/​ReferenceAssemblyModel.cs Models grain-reference factories.
src/​Orleans.CodeGenerator/​Model/​ProxyInterfaceModelExtractor.cs Detects compatible proxy bases.
src/​Orleans.CodeGenerator/​Model/​ProxyInterfaceModel.cs Records factory support metadata.
src/​Orleans.CodeGenerator/​Model/​MetadataAggregateModelBuilder.cs Preserves factory metadata during normalization.
src/​Orleans.CodeGenerator/​MetadataGenerator.cs Emits direct factory registrations.
src/​Orleans.CodeGenerator/​Diagnostics/​InvalidGrainReferenceFactoryDiagnostic.cs Defines invalid-registration diagnostics.
src/​Orleans.CodeGenerator/​Diagnostics/​DiagnosticRuleId.cs Adds diagnostic identifier ORLEANS0117.
src/​Orleans.CodeGenerator/​AnalyzerReleases.Unshipped.md Records the new analyzer rule.
src/​api/​Orleans.Serialization/​Orleans.Serialization.cs Updates generated serialization API surface.
src/​api/​Orleans.Core.Abstractions/​Orleans.Core.Abstractions.cs Updates generated core API surface.
docs/​site/​src/​content/​docs/​implementation/​serialization.md Documents factory construction and compatibility.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Orleans.CodeGenerator/MetadataGenerator.cs Outdated
Comment thread src/Orleans.Core/GrainReferences/GrainReferenceActivator.cs
Copilot AI balanced review requested due to automatic review settings October 2, 2026 04:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The implementation, compatibility paths, generated APIs, documentation, and focused test coverage are consistent and complete.

Review effort: Balanced
Findings: None

Resolved since last review (2)

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage

Metric Pull request
Lines 82.92% (115,683 / 139,516)
Branches 72.33% (33,690 / 46,581)

Report-only conclusion: current-main baseline stale.

The newest successful coverage run tested cdb7961, not current main d4e4620.

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

Copilot AI balanced review requested due to automatic review settings October 2, 2026 18:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It changes central code-generation and grain-reference activation paths across JIT, trimming, and NativeAOT environments.

Review effort: Balanced
Findings: None

Copilot AI balanced review requested due to automatic review settings October 2, 2026 18:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The cross-cutting code-generation, runtime activation, compatibility, and NativeAOT changes warrant final human validation despite strong focused coverage.

Review effort: Balanced
Findings: None

Copilot AI balanced review requested due to automatic review settings October 2, 2026 19:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Factory-result validation currently permits user-defined conversions that can return a non-proxy object.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Comment thread src/Orleans.CodeGenerator/Model/ProxyInterfaceDescription.cs Outdated
Copilot AI balanced review requested due to automatic review settings October 2, 2026 21:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It spans public APIs, source generation, runtime activation, compatibility behavior, and NativeAOT construction paths.

Review effort: Balanced
Findings: None

Resolved since last review (1)

@ReubenBond
ReubenBond marked this pull request as draft October 2, 2026 21:54

This branch has not been deployed

No deployments
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.

2 participants