Background
CsWinRT relies on a couple of assembly-level settings being present on projects that consume it:
[assembly: DisableRuntimeMarshalling]
[assembly: AssemblyMetadata("IsAotCompatible", "True")] (i.e. IsAotCompatible)
Today these are emitted into the consuming project's generated source, via the projection writer's Resources/Base/AssemblyAttributes.cs base resource, which cswinrtprojectionrefgen writes into the project's generated-files folder and the project then compiles.
This is awkward for a couple of reasons:
- The attributes are only emitted as a side effect of running the reference projection generator. An authored component that references no input
.winmd files does not need to run that generator at all (see #-, "Skip the reference projection generator for input-less authored components"), so it would no longer get these attributes — meaning the project has to set them itself (which is what the smoke tests now do explicitly via DisableRuntimeMarshalling=true).
- More generally, emitting these as generated source is the wrong layer: they are really build defaults that should apply to any CsWinRT-consuming project, independent of whether any projection sources get generated.
Proposal
Stop emitting DisableRuntimeMarshalling / IsAotCompatible from generated source. Instead, add a .targets (or .props) in the Microsoft.Windows.CsWinRT package that runs before the .NET SDK common targets and sets these two properties to sensible defaults only if the user has not already set them explicitly, e.g.:
<PropertyGroup>
<DisableRuntimeMarshalling Condition="'$(DisableRuntimeMarshalling)' == ''">true</DisableRuntimeMarshalling>
<IsAotCompatible Condition="'$(IsAotCompatible)' == ''">true</IsAotCompatible>
</PropertyGroup>
(The .NET SDK already translates the DisableRuntimeMarshalling and IsAotCompatible MSBuild properties into the corresponding assembly attributes during GenerateAssemblyInfo, so wiring the properties is sufficient — no source emission required.)
This makes the defaults:
- Uniform — every CsWinRT-consuming project gets them, not just ones that generate projection sources.
- Overridable — users can opt out by setting the property explicitly.
- Decoupled from the projection generator, so skipping the generator (for input-less components, etc.) no longer changes these defaults.
Notes / care
- Must run before the .NET SDK common targets so the property values are observed by
GenerateAssemblyInfo.
- Must guard against the duplicate-attribute error (
CS0579): once the package sets the property, generated source must no longer also emit [assembly: DisableRuntimeMarshalling], otherwise both the SDK-generated attribute and the source attribute would collide. So this change should land together with removing the attribute emission from Resources/Base/AssemblyAttributes.cs.
- Verify behavior for all CsWinRT-consuming project shapes: apps, libraries, authored components (with and without input
.winmd files), and the WUX/WinUI variants.
Context
This was identified while wiring up the end-to-end smoke tests (consumption + authoring) against the real NuGet package. The immediate unblock was to skip the reference projection generator for input-less components and have the smoke test project set DisableRuntimeMarshalling=true itself; this issue tracks doing it properly for all consumers.
Background
CsWinRT relies on a couple of assembly-level settings being present on projects that consume it:
[assembly: DisableRuntimeMarshalling][assembly: AssemblyMetadata("IsAotCompatible", "True")](i.e.IsAotCompatible)Today these are emitted into the consuming project's generated source, via the projection writer's
Resources/Base/AssemblyAttributes.csbase resource, whichcswinrtprojectionrefgenwrites into the project's generated-files folder and the project then compiles.This is awkward for a couple of reasons:
.winmdfiles does not need to run that generator at all (see #-, "Skip the reference projection generator for input-less authored components"), so it would no longer get these attributes — meaning the project has to set them itself (which is what the smoke tests now do explicitly viaDisableRuntimeMarshalling=true).Proposal
Stop emitting
DisableRuntimeMarshalling/IsAotCompatiblefrom generated source. Instead, add a.targets(or.props) in theMicrosoft.Windows.CsWinRTpackage that runs before the .NET SDK common targets and sets these two properties to sensible defaults only if the user has not already set them explicitly, e.g.:(The .NET SDK already translates the
DisableRuntimeMarshallingandIsAotCompatibleMSBuild properties into the corresponding assembly attributes duringGenerateAssemblyInfo, so wiring the properties is sufficient — no source emission required.)This makes the defaults:
Notes / care
GenerateAssemblyInfo.CS0579): once the package sets the property, generated source must no longer also emit[assembly: DisableRuntimeMarshalling], otherwise both the SDK-generated attribute and the source attribute would collide. So this change should land together with removing the attribute emission fromResources/Base/AssemblyAttributes.cs..winmdfiles), and the WUX/WinUI variants.Context
This was identified while wiring up the end-to-end smoke tests (consumption + authoring) against the real NuGet package. The immediate unblock was to skip the reference projection generator for input-less components and have the smoke test project set
DisableRuntimeMarshalling=trueitself; this issue tracks doing it properly for all consumers.