Skip to content

Add reference assembly support for WinRT.Runtime#2377

Draft
Sergio0694 wants to merge 13 commits intostaging/3.0from
user/sergiopedri/winrt-runtime-ref-assembly
Draft

Add reference assembly support for WinRT.Runtime#2377
Sergio0694 wants to merge 13 commits intostaging/3.0from
user/sergiopedri/winrt-runtime-ref-assembly

Conversation

@Sergio0694
Copy link
Copy Markdown
Member

@Sergio0694 Sergio0694 commented Mar 30, 2026

Summary

Add reference assembly support for WinRT.Runtime by using #if !REFERENCE_ASSEMBLY to strip private implementation detail types and members from the reference assembly output. This replaces the previous [Obsolete] / [EditorBrowsable(Never)] approach, completely hiding implementation details from the versioned API surface.

Motivation

WinRT.Runtime has many public types that are "private implementation details" — they're public only because generated code in other assemblies needs to call them, but they're not part of the versioned API surface. Previously these were marked with [Obsolete] and [EditorBrowsable(Never)] attributes, but those attributes were still visible to consumers and didn't truly hide the types. With the reference assembly approach, these types are completely stripped from the reference assembly, making them invisible to downstream consumers while still available in the implementation assembly for generated code to use.

The project is now built twice for NuGet packaging:

  1. Normal build → produces the implementation assembly (for lib\net10.0\ in the NuGet)
  2. With CsWinRTBuildReferenceAssembly=true → produces a reference assembly (for ref\net10.0\ in the NuGet) with implementation details stripped

Changes

  • src/WinRT.Runtime2/WinRT.Runtime.csproj: Define REFERENCE_ASSEMBLY constant when CsWinRTBuildReferenceAssembly=true; disable ProduceReferenceAssembly for normal builds so ProjectReference consumers compile against the impl assembly; add warning suppressions for ref assembly build
  • ~400 .cs files in src/WinRT.Runtime2/: Add #if !REFERENCE_ASSEMBLY guards to strip implementation detail types (ABI marshallers, vtable structs, native object wrappers, callbacks, collection adapters, async adapters, stream adapters, platform imports, placeholders, type map infrastructure, projection impls, object reference types, activation helpers, etc.)
  • ~32 .cs files in src/WinRT.Runtime2/: Wrap implementation-detail attributes ([WindowsRuntimeMetadata], [ABI.*], etc.) on public types that remain in the ref assembly
  • ~9 .cs files in src/WinRT.Runtime2/: Wrap method bodies that reference removed types with #if !REFERENCE_ASSEMBLY / #else throw null!;
  • WindowsRuntimeObject.cs: Special handling — class declaration always visible, implementation members wrapped, explicit interface implementations have body wrapping; HasUnwrappableNativeObjectReference and IsOverridableInterface restored to abstract (reverting PR Hide HasUnwrappableNativeObjectReference and IsOverridableInterface from reference projections #2371 workaround)
  • WellKnownInterfaceIIDs.tt and IPropertyValueImpl.BlittableValueTypeArray.tt: T4 templates updated to emit #if !REFERENCE_ASSEMBLY guards
  • Deleted: Properties/WindowsRuntimeConstants.cs (contained only constants for the removed [Obsolete] attributes)
  • Deleted: docs/diagnostics/cswinrt30001.md (CSWINRT3001 diagnostic no longer applicable)
  • build/ and nuget/: Build pipeline and NuGet packaging updates for dual assembly builds
  • .github/copilot-instructions.md: Updated to document reference assembly build setup
  • .github/skills/interop-generator/SKILL.md: Updated to explain private implementation detail APIs and how the interop generator uses the implementation assembly
  • .github/skills/update-copilot-instructions/SKILL.md: Added reference assembly verification step

Sergio0694 and others added 13 commits March 29, 2026 18:20
Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
…e assembly

Use #if !REFERENCE_ASSEMBLY to exclude impl-detail types and members from
the reference assembly output. This covers ABI marshallers, vtable structs,
native object wrappers, callbacks, collections adapters, async adapters,
stream adapters, platform imports, placeholders, type map infrastructure,
projection impls, object reference types, activation helpers, and related
internal types. Public types that remain visible have their impl-detail
attributes and method bodies conditionally compiled out. Global using
aliases (HRESULT, HSTRING, etc.) are left visible as they do not affect
the public API surface.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove file-level #if !REFERENCE_ASSEMBLY guards from files where all
contained types are non-public (internal or file-scoped) and the file
compiles without the guard when producing the reference assembly. The
compiler automatically strips non-public types from reference assemblies,
so these guards are redundant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wrap implementation-only APIs and types with #if !REFERENCE_ASSEMBLY to exclude them from reference-assembly builds (WindowsRuntimeActivationFactory, WellKnownExceptionDataKeys, CreateObjectReferenceFlags, RestrictedErrorInfo). Minor doc comment rewording in NullPlaceholder for clarity. Add #pragma to suppress CS1574 in WindowsRuntimeFeatureSwitches and remove CS1574/CS1587 from the project NoWarn list.
Remove inner #if !REFERENCE_ASSEMBLY / #else throw null! / #endif blocks
that were already inside an outer #if !REFERENCE_ASSEMBLY scope, making
them redundant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These [Obsolete] and [EditorBrowsable(Never)] attributes are no longer
needed now that implementation detail types are stripped from the
reference assembly via #if !REFERENCE_ASSEMBLY.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This diagnostic is no longer applicable now that the private
implementation detail [Obsolete] attributes have been removed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update copilot-instructions.md and interop-generator SKILL.md to reflect
that private implementation detail types are now excluded from the
reference assembly via #if !REFERENCE_ASSEMBLY, rather than being marked
with [Obsolete] and [EditorBrowsable(Never)] attributes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Expand the version compatibility section to explain how the interop
generator uses WinRT.Runtime's implementation assembly (not the reference
assembly) to access private implementation detail APIs, with concrete
examples of the type categories involved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert HasUnwrappableNativeObjectReference and IsOverridableInterface
back to abstract (from virtual with UnreachableException.Throw() body).
These members are now inside #if !REFERENCE_ASSEMBLY, so the workaround
from PR #2371 is no longer needed. Also remove the UnreachableException
extension method that was added solely to support those virtual stubs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
WinRT.Runtime provides its own custom reference assembly (built with
CsWinRTBuildReferenceAssembly=true) that strips private implementation
detail types. Disable the SDK's default ProduceReferenceAssembly so that
downstream ProjectReference consumers compile against the implementation
assembly directly, where abstract members like HasUnwrappableNativeObject-
Reference and IsOverridableInterface are visible and can be overridden.
NuGet consumers continue to get the custom ref assembly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Sergio0694 Sergio0694 requested a review from manodasanW March 30, 2026 19:08
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.

1 participant