fix: support single-file metadata discovery - #11054
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes align with the PR’s stated single-file goals, add explicit compatibility contracts for file-based APIs, and include targeted tests covering the new behavior.
Review tier: Lite
Findings: None
What changed in this PR
This PR improves Orleans’ compatibility with .NET single-file deployments by removing reliance on file-based assembly metadata (Assembly.Location, DependencyContext.Load) in core runtime version reporting and serialization application-part discovery, while making file-based discovery explicitly opt-in/annotated.
Changes:
- Update runtime version reporting to use
AssemblyInformationalVersionAttribute(with assembly-version fallback) so it works when assemblies have no physical path. - Rework serialization application-part discovery to start from generated
ApplicationPartAttributemetadata + loaded assemblies, and gate dependency-context scanning behind an “assembly files available” check withRequiresAssemblyFiles. - Add focused unit tests and enable the single-file analyzer for the affected
net10.0targets.
| File | Description |
|---|---|
| test/Orleans.Serialization.UnitTests/ReferencedAssemblyProviderTests.cs | Adds tests validating application-part traversal and the RequiresAssemblyFiles contract. |
| test/Orleans.Core.Tests/RuntimeVersionTests.cs | Adds tests ensuring runtime version reporting works for fileless/dynamic assemblies. |
| src/Orleans.Serialization/Orleans.Serialization.csproj | Enables the single-file analyzer for net10.0 builds. |
| src/Orleans.Serialization/Hosting/ReferencedAssemblyProvider.cs | Switches discovery to entry-assembly/generated metadata + loaded assemblies; gates dependency-context scanning behind file availability and annotates file-based API. |
| src/Orleans.Core/Runtime/RuntimeVersion.cs | Replaces file-based product version lookup with informational-version attribute lookup and preserves fallback behavior. |
| src/Orleans.Core/Orleans.Core.csproj | Enables the single-file analyzer for net10.0 builds. |
| src/api/Orleans.Serialization/Orleans.Serialization.cs | Updates the public API surface to include the RequiresAssemblyFiles annotation on dependency-context discovery. |
💡 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 114a827, not current main 9cf2fac. 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 |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes align with the stated single-file compatibility goals, keep a clear compatibility contract via RequiresAssemblyFiles, and include targeted unit test coverage for the new behaviors.
Review tier: Lite
Findings: None
|
The Azure Storage net8 failure is unrelated to this change and is tracked by #11033 (SMS_StreamRel_AllSilosRestart_PubSubCounts observed publisher count 2 instead of 1 after restart). The failed job has been rerun on the unchanged PR head. |
da70def to
5556532
Compare
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The functional changes align with the stated single-file goals and are backed by focused tests, with only a minor doc-comment inconsistency noted.
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
src/Orleans.Core/Runtime/RuntimeVersion.cs — The XML doc comment for Current still describes the old FileVersionInfo.ProductVersion format… |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The new AssemblyFilesAvailable gate can incorrectly disable dependency-context discovery when the entry assembly is dynamic, even though the discovery path supports dynamic assemblies via DependencyContext.Default.
Review tier: Lite
Findings: None
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
src/Orleans.Core/Runtime/RuntimeVersion.cs — The XML doc comment for Current still describes the old FileVersionInfo.ProductVersion format… View resolved comment |
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Orleans.Serialization/Hosting/ReferencedAssemblyProvider.cs:225
- AssemblyFilesAvailable treats a dynamic entry assembly as “no assembly files available” because it always prefers the entry assembly when non-null. That prevents dependency-context discovery even though AddFromDependencyContext explicitly handles dynamic assemblies via DependencyContext.Default. Consider falling back to the provider assembly when the entry assembly is dynamic so the availability check matches the discovery behavior.
Addressed in |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes align with the PR’s stated single-file compatibility goals and include targeted test coverage for the new behavior and contracts.
Review tier: Lite
Findings: None
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Orleans.Serialization/Hosting/ReferencedAssemblyProvider.cs:137
- The
RequiresAssemblyFilesmessage hard-codesGetRelevantAssembliesas a string, so a rename would silently leave the guidance stale. Sincenameof(...)is a compile-time constant, you can embed it in the message to keep it refactor-safe.
Addressed in |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes align with the stated single-file compatibility goals and include targeted tests, with only minor build-target optimization feedback noted.
Review tier: Lite
Findings: None
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
test/Orleans.Serialization.UnitTests/Orleans.Serialization.UnitTests.csproj:55
- The
CopyNetStandardSerializationAssettarget runs on every net10 build (including design-time builds) and always copies the asset, which can add noticeable overhead in IDE/design-time evaluation and repeated builds. Consider gating the target onDesignTimeBuildand settingSkipUnchangedFileson theCopytask to avoid unnecessary work.
Addressed in |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes are narrowly scoped, align with the PR’s stated single-file compatibility goals, and are backed by targeted unit tests covering the new behaviors and contracts.
Review tier: Lite
Findings: None
|
The BVT failures were caused by AssemblyFileAvailabilityIsFalseForMemoryLoadedAssembly loading a second copy of the Orleans.Serialization.UnitTests assembly, which exposed duplicate generated metadata providers to later tests. Fixed in 36e0d82 by using a framework assembly with no Orleans application-part metadata for the memory-loaded probe. The full Orleans.Serialization.UnitTests BVT suite now passes: 4,050/4,050. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
ReferencedAssemblyProvider.GetRelevantAssemblies() now calls AddAssembly, which currently results in infinite recursion/stack overflow due to the AddAssembly implementation.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Lite
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
src/Orleans.Serialization/Hosting/ReferencedAssemblyProvider.cs — GetRelevantAssemblies now calls AddAssembly, but AddAssembly currently calls itself… |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The changes are cohesive, include appropriate analyzer annotations, and are backed by targeted tests covering the new single-file-safe behaviors.
Review tier: Lite
Findings: None
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
src/Orleans.Serialization/Hosting/ReferencedAssemblyProvider.cs — GetRelevantAssemblies now calls AddAssembly, but AddAssembly currently calls itself… View resolved comment |


Problem
The .NET single-file analyzer reported file-based metadata access in runtime version reporting and serializer application-part discovery. Bundled assemblies have no
Assembly.Location, andDependencyContextdiscovery requires physical assembly files.Solution
Read the runtime product version from
AssemblyInformationalVersionAttribute, preserving the assembly-version fallback and build-configuration suffix. Serializer discovery now starts from generatedApplicationPartAttributemetadata and loaded assemblies, while dependency-context discovery runs only when assembly files are available. The public file-based API is annotated withRequiresAssemblyFiles, and the single-file analyzer is enabled for the affected net10 projects. Focused tests cover fileless version metadata, generated application-part traversal, entry-assembly discovery, and the public assembly-file contract.Rationale
Assembly attributes and generated application-part registrations are available from memory-loaded assemblies, so they provide stable metadata and discovery in bundled apps. Framework-dependent deployments retain dependency-context scanning for assemblies which have not yet loaded, while callers of the explicit file-based API receive an accurate compatibility contract.
Microsoft Reviewers: Open in CodeFlow