diff --git a/src/WinRT.Generator.Tasks/RunCsWinRTInteropGenerator.cs b/src/WinRT.Generator.Tasks/RunCsWinRTInteropGenerator.cs
index 7537fd9ab..4bda5d364 100644
--- a/src/WinRT.Generator.Tasks/RunCsWinRTInteropGenerator.cs
+++ b/src/WinRT.Generator.Tasks/RunCsWinRTInteropGenerator.cs
@@ -44,13 +44,23 @@ public sealed class RunCsWinRTInteropGenerator : ToolTask
public ITaskItem[]? OutputAssemblyPath { get; set; }
///
- /// Gets or sets the path to the WinRT merged projection assembly.
+ /// Gets or sets the path to the WinRT Windows SDK projection assembly (i.e. WinRT.Sdk.Projection.dll).
///
[Required]
+ public ITaskItem? WinRTSdkProjectionAssemblyPath { get; set; }
+
+ ///
+ /// Gets or sets the path to the WinRT Windows SDK XAML projection assembly (i.e. WinRT.Sdk.Xaml.Projection.dll).
+ ///
+ public ITaskItem? WinRTSdkXamlProjectionAssemblyPath { get; set; }
+
+ ///
+ /// Gets or sets the path to the WinRT merged projection assembly (i.e. WinRT.Projection.dll).
+ ///
public ITaskItem? WinRTProjectionAssemblyPath { get; set; }
///
- /// Gets or sets the path to the WinRT merged component assembly generated for authoring scenarios.
+ /// Gets or sets the path to the WinRT merged component assembly generated for authoring scenarios (i.e. WinRT.Component.dll).
///
public ITaskItem? WinRTComponentAssemblyPath { get; set; }
@@ -160,9 +170,9 @@ protected override bool ValidateParameters()
return false;
}
- if (WinRTProjectionAssemblyPath is null)
+ if (WinRTSdkProjectionAssemblyPath is null)
{
- Log.LogWarning("Invalid 'WinRTProjectionAssemblyPath' input.");
+ Log.LogWarning("Invalid 'WinRTSdkProjectionAssemblyPath' input.");
return false;
}
@@ -254,7 +264,9 @@ protected override string GenerateResponseFileCommands()
AppendResponseFileCommand(args, "--reference-assembly-paths", referenceAssemblyPathsArg);
AppendResponseFileCommand(args, "--implementation-assembly-paths", implementationAssemblyPathsArg);
AppendResponseFileCommand(args, "--output-assembly-path", EffectiveOutputAssemblyItemSpec);
- AppendResponseFileCommand(args, "--winrt-projection-assembly-path", WinRTProjectionAssemblyPath!.ItemSpec);
+ AppendResponseFileCommand(args, "--winrt-sdk-projection-assembly-path", WinRTSdkProjectionAssemblyPath!.ItemSpec);
+ AppendResponseFileOptionalCommand(args, "--winrt-sdk-xaml-projection-assembly-path", WinRTSdkXamlProjectionAssemblyPath?.ItemSpec);
+ AppendResponseFileOptionalCommand(args, "--winrt-projection-assembly-path", WinRTProjectionAssemblyPath?.ItemSpec);
AppendResponseFileOptionalCommand(args, "--winrt-component-assembly-path", WinRTComponentAssemblyPath?.ItemSpec);
AppendResponseFileCommand(args, "--generated-assembly-directory", InteropAssemblyDirectory!);
AppendResponseFileOptionalCommand(args, "--debug-repro-directory", DebugReproDirectory);
diff --git a/src/WinRT.Impl.Generator/Generation/ImplGenerator.cs b/src/WinRT.Impl.Generator/Generation/ImplGenerator.cs
index 4696c8763..7e2f004af 100644
--- a/src/WinRT.Impl.Generator/Generation/ImplGenerator.cs
+++ b/src/WinRT.Impl.Generator/Generation/ImplGenerator.cs
@@ -12,6 +12,7 @@
using System.Security;
using System.Security.Permissions;
using System.Threading;
+using AsmResolver;
using AsmResolver.DotNet;
using AsmResolver.PE.DotNet.StrongName;
using ConsoleAppFramework;
@@ -242,15 +243,38 @@ private static void EmitTypeForwards(ModuleDefinition inputModule, ModuleDefinit
{
try
{
- // We need an assembly reference for the merged projection .dll that will be generated.
+ // We need an assembly reference for the precompiled projection .dll for the Windows SDK.
// The version doesn't matter here (as long as it's not '255.255.255.255'). The real .dll
// will always have a version number equal or higher than this, so it will load correctly.
+ AssemblyReference sdkProjectionAssembly = new("WinRT.Sdk.Projection"u8, new Version(0, 0, 0, 0))
+ {
+ PublicKeyOrToken = ImplValues.PublicKeyData,
+ HasPublicKey = true
+ };
+
+ // Similar as above, but for the precompiled XAML projection .dll for Windows SDK XAML types.
+ // This is only used when the option to use Windows UI Xaml projections is enabled.
+ AssemblyReference sdkXamlProjectionAssembly = new("WinRT.Sdk.Xaml.Projection"u8, new Version(0, 0, 0, 0))
+ {
+ PublicKeyOrToken = ImplValues.PublicKeyData,
+ HasPublicKey = true
+ };
+
+ // Similar as above, but for the merged projection .dll for all other Windows Runtime types.
+ // Unlike the implementation .dll for the Windows SDK however, this .dll is created on the fly.
AssemblyReference projectionAssembly = new("WinRT.Projection"u8, new Version(0, 0, 0, 0))
{
PublicKeyOrToken = ImplValues.PublicKeyData,
HasPublicKey = true
};
+ // Check if the input module is either of the Windows SDK reference assemblies. Types
+ // from the XAML assembly belong to the XAML projection .dll, while types from the SDK
+ // assembly belong to the standard SDK projection .dll. All other types are forwarded
+ // to the merged projection .dll, which is generated at final build time.
+ bool isSdkModule = inputModule.Assembly?.Name is Utf8String sdkName && sdkName.AsSpan().SequenceEqual("Microsoft.Windows.SDK.NET"u8);
+ bool isXamlModule = inputModule.Assembly?.Name is Utf8String xamlName && xamlName.AsSpan().SequenceEqual("Microsoft.Windows.UI.Xaml"u8);
+
foreach (TypeDefinition exportedType in inputModule.TopLevelTypes)
{
// We only need to forward public types
@@ -259,9 +283,23 @@ private static void EmitTypeForwards(ModuleDefinition inputModule, ModuleDefinit
continue;
}
+ // Also make sure the type has a valid namespace, otherwise we can't handle it
+ if (exportedType.Namespace is null)
+ {
+ continue;
+ }
+
+ // Determine the target assembly based on the declaring assembly of the current type.
+ // This matches the logic in 'cswinrtinteropgen' to figure out the right one.
+ AssemblyReference implementationAssembly = isXamlModule
+ ? sdkXamlProjectionAssembly
+ : isSdkModule
+ ? sdkProjectionAssembly
+ : projectionAssembly;
+
// Emit the type forwards for all public (projected) types
implModule.ExportedTypes.Add(new ExportedType(
- implementation: projectionAssembly.ImportWith(implModule.DefaultImporter),
+ implementation: implementationAssembly.ImportWith(implModule.DefaultImporter),
ns: exportedType.Namespace,
name: exportedType.Name)
{
diff --git a/src/WinRT.Interop.Generator/Builders/IgnoresAccessChecksToBuilder.cs b/src/WinRT.Interop.Generator/Builders/IgnoresAccessChecksToBuilder.cs
index 1b73fd3e5..d00bffcd9 100644
--- a/src/WinRT.Interop.Generator/Builders/IgnoresAccessChecksToBuilder.cs
+++ b/src/WinRT.Interop.Generator/Builders/IgnoresAccessChecksToBuilder.cs
@@ -17,11 +17,17 @@ internal static partial class IgnoresAccessChecksToBuilder
///
/// Defines all assembly attributes for target modules using the Windows TFM.
///
+ /// The for the Windows Runtime XAML projection assembly (i.e. WinRT.Sdk.Xaml.Projection.dll).
+ /// The for the Windows Runtime projection assembly (i.e. WinRT.Projection.dll).
+ /// The for the Windows Runtime component assembly (i.e. WinRT.Component.dll).
/// The input set of reference path modules.
/// The instance to use.
/// The instance to use.
/// The interop module being built.
public static void AssemblyAttributes(
+ ModuleDefinition? winRTSdkXamlProjectionModule,
+ ModuleDefinition? winRTProjectionModule,
+ ModuleDefinition? winRTComponentModule,
IEnumerable referencePathModules,
InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
@@ -43,8 +49,27 @@ public static void AssemblyAttributes(
module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.IgnoresAccessChecksTo(assemblyName, interopDefinitions, interopReferences));
}
- // We also always add an attribute for 'WinRT.Projection', which is the merged Windows Runtime projection assembly.
- // This assembly is generated at compile time by another task, and will not be present in the set of reference paths.
- module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.IgnoresAccessChecksTo("WinRT.Projection", interopDefinitions, interopReferences));
+ // We also always add an attribute for 'WinRT.Sdk.Projection', which is the precompiled projection .dll for the Windows SDK
+ module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.IgnoresAccessChecksTo("WinRT.Sdk.Projection", interopDefinitions, interopReferences));
+
+ // For 'WinRT.Sdk.Xaml.Projection', which is the precompiled projection .dll for Windows SDK XAML types, we only
+ // need the attribute if we do have that .dll being passed as input. That is only if XAML projections are enabled.
+ if (winRTSdkXamlProjectionModule is not null)
+ {
+ module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.IgnoresAccessChecksTo("WinRT.Sdk.Xaml.Projection", interopDefinitions, interopReferences));
+ }
+
+ // For 'WinRT.Projection', which is the merged Windows Runtime projection assembly that is generated at final build time,
+ // we only need the attribute if we do have that .dll being passed as input. That is only if we have any 3rd party types.
+ if (winRTProjectionModule is not null)
+ {
+ module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.IgnoresAccessChecksTo("WinRT.Projection", interopDefinitions, interopReferences));
+ }
+
+ // Similarly, we need an attribute for 'WinRT.Component' only if we reference some components and we do have this .dll
+ if (winRTComponentModule is not null)
+ {
+ module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.IgnoresAccessChecksTo("WinRT.Component", interopDefinitions, interopReferences));
+ }
}
}
\ No newline at end of file
diff --git a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs
index 949449d96..59835c960 100644
--- a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs
+++ b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs
@@ -10,6 +10,8 @@
using AsmResolver.PE.DotNet.Metadata.Tables;
using WindowsRuntime.InteropGenerator.References;
+#pragma warning disable IDE0046
+
namespace WindowsRuntime.InteropGenerator;
///
@@ -61,6 +63,44 @@ public bool TryGetGuidAttribute(InteropReferences interopReferences, out Guid ii
extension(ITypeDescriptor type)
{
+ ///
+ /// Gets a value indicating whether the type is a projected Windows SDK type (not custom-mapped or manually-projected).
+ ///
+ public bool IsProjectedWindowsSdkType
+ {
+ get
+ {
+ // Types from 'Microsoft.Windows.SDK.NET.dll' belong to the SDK projection .dll. We check
+ // the declaring assembly name to reliably determine the origin of the type. We also optimize
+ // when an UTF8 value is available to avoid redundant UTF8 transcoding work.
+ if (type is TypeDefinition { DeclaringModule.Assembly.Name: Utf8String name })
+ {
+ return name.AsSpan().SequenceEqual(InteropNames.WindowsSDKAssemblyNameUtf8);
+ }
+
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the type is a projected Windows SDK XAML type (from Microsoft.Windows.UI.Xaml.dll).
+ ///
+ public bool IsProjectedWindowsSdkXamlType
+ {
+ get
+ {
+ // Types from 'Microsoft.Windows.UI.Xaml.dll' belong to the XAML projection .dll. We check the
+ // declaring assembly name to reliably determine the origin of the type, as types from this
+ // assembly may span various 'Windows.*' sub-namespaces that can't be easily pattern-matched.
+ if (type is TypeDefinition { DeclaringModule.Assembly.Name: Utf8String name })
+ {
+ return name.AsSpan().SequenceEqual(InteropNames.WindowsSDKXamlAssemblyNameUtf8);
+ }
+
+ return false;
+ }
+ }
+
///
/// Checks whether an is some type.
///
@@ -591,8 +631,15 @@ public TypeSignature GetAbiType(InteropReferences interopReferences)
return interopReferences.AbiDateTimeOffset.ToValueTypeSignature();
}
- // Otherwise, we can rely on the blittable type being defined in the same module under the 'ABI' namespace
- return interopReferences.WinRTProjection.CreateTypeReference(
+ // Determine the right assembly reference for this projected type
+ AssemblyReference projectionAssembly = type.IsProjectedWindowsSdkXamlType
+ ? interopReferences.WinRTSdkXamlProjection
+ : type.IsProjectedWindowsSdkType
+ ? interopReferences.WinRTSdkProjection
+ : interopReferences.WinRTProjection;
+
+ // For all types that get here, their ABI types will be in the right projection assembly, under the 'ABI' namespace
+ return projectionAssembly.CreateTypeReference(
ns: (Utf8String)$"ABI.{typeDefinition.Namespace}",
name: typeDefinition.Name!).ToValueTypeSignature();
}
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs
index f3bf470e0..8055f5b65 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs
@@ -76,6 +76,8 @@ private static string UnpackDebugRepro(string path, CancellationToken token)
List referencePaths = [];
List implementationPaths = [];
string? outputAssemblyPath = null;
+ string? winRTSdkProjectionAssemblyPath = null;
+ string? winRTSdkXamlProjectionAssemblyPath = null;
string? winRTProjectionAssemblyPath = null;
string? winRTComponentAssemblyPath = null;
@@ -142,7 +144,15 @@ private static string UnpackDebugRepro(string path, CancellationToken token)
}
// Also track the private implementation detail .dll-s (these are also in the set of references)
- if (dllEntry.Name == args.WinRTProjectionAssemblyPath)
+ if (dllEntry.Name == args.WinRTSdkProjectionAssemblyPath)
+ {
+ winRTSdkProjectionAssemblyPath = destinationPath;
+ }
+ else if (args.WinRTSdkXamlProjectionAssemblyPath is not null && dllEntry.Name == args.WinRTSdkXamlProjectionAssemblyPath)
+ {
+ winRTSdkXamlProjectionAssemblyPath = destinationPath;
+ }
+ else if (args.WinRTProjectionAssemblyPath is not null && dllEntry.Name == args.WinRTProjectionAssemblyPath)
{
winRTProjectionAssemblyPath = destinationPath;
}
@@ -160,7 +170,9 @@ private static string UnpackDebugRepro(string path, CancellationToken token)
ReferenceAssemblyPaths = [.. referencePaths],
ImplementationAssemblyPaths = [.. implementationPaths],
OutputAssemblyPath = outputAssemblyPath!,
- WinRTProjectionAssemblyPath = winRTProjectionAssemblyPath!,
+ WinRTSdkProjectionAssemblyPath = winRTSdkProjectionAssemblyPath!,
+ WinRTSdkXamlProjectionAssemblyPath = winRTSdkXamlProjectionAssemblyPath,
+ WinRTProjectionAssemblyPath = winRTProjectionAssemblyPath,
WinRTComponentAssemblyPath = winRTComponentAssemblyPath,
GeneratedAssemblyDirectory = tempDirectory,
UseWindowsUIXamlProjections = args.UseWindowsUIXamlProjections,
@@ -226,7 +238,9 @@ private static void SaveDebugRepro(InteropGeneratorArgs args)
// Hash and copy the well known assemblies we use as input
string outputAssemblyHashedName = CopyHashedFileToDirectory(args.OutputAssemblyPath, tempDirectory, originalImplementationDllPaths, args.Token);
- string winRTProjectionAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTProjectionAssemblyPath, implementationDirectory, originalImplementationDllPaths, args.Token);
+ string winRTSdkProjectionAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTSdkProjectionAssemblyPath, implementationDirectory, originalImplementationDllPaths, args.Token);
+ string? winRTSdkXamlProjectionAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTSdkXamlProjectionAssemblyPath, implementationDirectory, originalImplementationDllPaths, args.Token);
+ string? winRTProjectionAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTProjectionAssemblyPath, implementationDirectory, originalImplementationDllPaths, args.Token);
string? winRTComponentAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTComponentAssemblyPath, implementationDirectory, originalImplementationDllPaths, args.Token);
args.Token.ThrowIfCancellationRequested();
@@ -237,6 +251,8 @@ private static void SaveDebugRepro(InteropGeneratorArgs args)
ReferenceAssemblyPaths = [.. updatedReferenceDllNames],
ImplementationAssemblyPaths = [.. updatedImplementationDllNames],
OutputAssemblyPath = outputAssemblyHashedName,
+ WinRTSdkProjectionAssemblyPath = winRTSdkProjectionAssemblyHashedName,
+ WinRTSdkXamlProjectionAssemblyPath = winRTSdkXamlProjectionAssemblyHashedName,
WinRTProjectionAssemblyPath = winRTProjectionAssemblyHashedName,
WinRTComponentAssemblyPath = winRTComponentAssemblyHashedName,
GeneratedAssemblyDirectory = args.GeneratedAssemblyDirectory,
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs
index 9321ba701..c44e9d482 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs
@@ -40,8 +40,9 @@ private static InteropGeneratorDiscoveryState Discover(InteropGeneratorArgs args
// No additional parameters will be passed to later steps: all the info is in this object.
InteropGeneratorDiscoveryState discoveryState = new() { AssemblyResolver = pathAssemblyResolver };
- // First, load the special 'WinRT.Projection.dll' and 'WinRT.Component.dll' modules (the latter is optional).
- // These are necessary for surfacing some information needed to generate code, that is not present otherwise.
+ // First, load the special 'WinRT.Sdk.Projection.dll', 'WinRT.Sdk.Xaml.Projection.dll', 'WinRT.Projection.dll'
+ // and 'WinRT.Component.dll' modules (the last three are optional). These are necessary for surfacing some
+ // information needed to generate code, that is not present otherwise.
LoadWinRTModules(args, discoveryState);
try
@@ -86,13 +87,33 @@ private static InteropGeneratorDiscoveryState Discover(InteropGeneratorArgs args
/// The discovery state for this invocation.
private static void LoadWinRTModules(InteropGeneratorArgs args, InteropGeneratorDiscoveryState discoveryState)
{
- // Load the 'WinRT.Projection.dll' module, this should always be available
- ModuleDefinition winRTProjectionModule = ModuleDefinition.FromFile(args.WinRTProjectionAssemblyPath, ((PathAssemblyResolver)discoveryState.AssemblyResolver).ReaderParameters);
+ // Load the 'WinRT.Sdk.Projection.dll' module, this should always be available
+ ModuleDefinition winRTSdkProjectionModule = ModuleDefinition.FromFile(args.WinRTSdkProjectionAssemblyPath, ((PathAssemblyResolver)discoveryState.AssemblyResolver).ReaderParameters);
- discoveryState.TrackWinRTProjectionModuleDefinition(winRTProjectionModule);
+ discoveryState.TrackWinRTSdkProjectionModuleDefinition(winRTSdkProjectionModule);
args.Token.ThrowIfCancellationRequested();
+ // Load the 'WinRT.Sdk.Xaml.Projection.dll' module, if available
+ if (args.WinRTSdkXamlProjectionAssemblyPath is not null)
+ {
+ ModuleDefinition winRTSdkXamlProjectionModule = ModuleDefinition.FromFile(args.WinRTSdkXamlProjectionAssemblyPath, ((PathAssemblyResolver)discoveryState.AssemblyResolver).ReaderParameters);
+
+ discoveryState.TrackWinRTSdkXamlProjectionModuleDefinition(winRTSdkXamlProjectionModule);
+
+ args.Token.ThrowIfCancellationRequested();
+ }
+
+ // Load the 'WinRT.Projection.dll' module, if available
+ if (args.WinRTProjectionAssemblyPath is not null)
+ {
+ ModuleDefinition winRTProjectionModule = ModuleDefinition.FromFile(args.WinRTProjectionAssemblyPath, ((PathAssemblyResolver)discoveryState.AssemblyResolver).ReaderParameters);
+
+ discoveryState.TrackWinRTProjectionModuleDefinition(winRTProjectionModule);
+
+ args.Token.ThrowIfCancellationRequested();
+ }
+
// Load the 'WinRT.Component.dll' module, if available
if (args.WinRTComponentAssemblyPath is not null)
{
@@ -115,10 +136,14 @@ private static void LoadAndProcessModule(
{
ReadOnlySpan fileName = Path.GetFileName(path.AsSpan());
- // Validate that the two possible private implementation detail .dll-s we expect have a matching path. These are:
+ // Validate that the possible private implementation detail .dll-s we expect have a matching path. These are:
+ // - 'WinRT.Sdk.Projection.dll': the precompiled projection assembly for the Windows SDK.
+ // - 'WinRT.Sdk.Xaml.Projection.dll': the precompiled projection assembly for the Windows SDK XAML types.
// - 'WinRT.Projection.dll': the generated merged projection assembly.
// - 'WinRT.Component.dll': the optional generated merged component assembly.
- if ((fileName.SequenceEqual(InteropNames.WindowsRuntimeProjectionDllName) && path != args.WinRTProjectionAssemblyPath) ||
+ if ((fileName.SequenceEqual(InteropNames.WindowsRuntimeSdkProjectionDllName) && path != args.WinRTSdkProjectionAssemblyPath) ||
+ (fileName.SequenceEqual(InteropNames.WindowsRuntimeSdkXamlProjectionDllName) && path != args.WinRTSdkXamlProjectionAssemblyPath) ||
+ (fileName.SequenceEqual(InteropNames.WindowsRuntimeProjectionDllName) && path != args.WinRTProjectionAssemblyPath) ||
(fileName.SequenceEqual(InteropNames.WindowsRuntimeComponentDllName) && path != args.WinRTComponentAssemblyPath))
{
throw WellKnownInteropExceptions.ReservedDllOriginalPathMismatch(fileName.ToString());
@@ -127,7 +152,9 @@ private static void LoadAndProcessModule(
// If the current module is one of those two .dll-s, we just skip it. They will be loaded separately (see above).
// However since they're also passed in the reference set (as they need to be referenced by the app directly),
// they will also show up here. This is intended, and it simplifies the targets (no need for them to filter items).
- if (fileName.SequenceEqual(InteropNames.WindowsRuntimeProjectionDllName) ||
+ if (fileName.SequenceEqual(InteropNames.WindowsRuntimeSdkProjectionDllName) ||
+ fileName.SequenceEqual(InteropNames.WindowsRuntimeSdkXamlProjectionDllName) ||
+ fileName.SequenceEqual(InteropNames.WindowsRuntimeProjectionDllName) ||
fileName.SequenceEqual(InteropNames.WindowsRuntimeComponentDllName))
{
return;
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs
index ec7be4a35..82d5e7e23 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs
@@ -47,7 +47,9 @@ private static void Emit(InteropGeneratorArgs args, InteropGeneratorDiscoverySta
InteropReferences interopReferences = new(module.CorLibTypeFactory, windowsRuntimeModule, windowsFoundationModule);
InteropDefinitions interopDefinitions = new(
interopReferences: interopReferences,
- windowsRuntimeProjectionModule: discoveryState.WinRTProjectionModuleDefinition!,
+ windowsRuntimeSdkProjectionModule: discoveryState.WinRTSdkProjectionModuleDefinition!,
+ windowsRuntimeSdkXamlProjectionModule: discoveryState.WinRTSdkXamlProjectionModuleDefinition,
+ windowsRuntimeProjectionModule: discoveryState.WinRTProjectionModuleDefinition,
windowsRuntimeComponentModule: discoveryState.WinRTComponentModuleDefinition);
args.Token.ThrowIfCancellationRequested();
@@ -2572,6 +2574,9 @@ private static void DefineIgnoresAccessChecksToAttributes(
// Next, emit all the '[IgnoresAccessChecksTo]' attributes for each type
IgnoresAccessChecksToBuilder.AssemblyAttributes(
+ winRTSdkXamlProjectionModule: discoveryState.WinRTSdkXamlProjectionModuleDefinition,
+ winRTProjectionModule: discoveryState.WinRTProjectionModuleDefinition,
+ winRTComponentModule: discoveryState.WinRTComponentModuleDefinition,
referencePathModules: discoveryState.ModuleDefinitions.Values.OrderByFullyQualifiedName(),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs
index 85d79fe34..5fced287d 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs
@@ -28,9 +28,23 @@ public string FormatToResponseFile()
_ = builder.Append(' ');
_ = builder.AppendLine(OutputAssemblyPath);
- _ = builder.Append(GetCommandLineArgumentName(nameof(WinRTProjectionAssemblyPath)));
+ _ = builder.Append(GetCommandLineArgumentName(nameof(WinRTSdkProjectionAssemblyPath)));
_ = builder.Append(' ');
- _ = builder.AppendLine(WinRTProjectionAssemblyPath);
+ _ = builder.AppendLine(WinRTSdkProjectionAssemblyPath);
+
+ if (WinRTSdkXamlProjectionAssemblyPath is not null)
+ {
+ _ = builder.Append(GetCommandLineArgumentName(nameof(WinRTSdkXamlProjectionAssemblyPath)));
+ _ = builder.Append(' ');
+ _ = builder.AppendLine(WinRTSdkXamlProjectionAssemblyPath);
+ }
+
+ if (WinRTProjectionAssemblyPath is not null)
+ {
+ _ = builder.Append(GetCommandLineArgumentName(nameof(WinRTProjectionAssemblyPath)));
+ _ = builder.Append(' ');
+ _ = builder.AppendLine(WinRTProjectionAssemblyPath);
+ }
if (WinRTComponentAssemblyPath is not null)
{
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs
index 9ebe6070e..89e4559ac 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs
@@ -100,7 +100,9 @@ private static InteropGeneratorArgs ParseFromResponseFile(string[] lines, Cancel
ReferenceAssemblyPaths = GetStringArrayArgument(argsMap, nameof(ReferenceAssemblyPaths)),
ImplementationAssemblyPaths = GetStringArrayArgument(argsMap, nameof(ImplementationAssemblyPaths)),
OutputAssemblyPath = GetStringArgument(argsMap, nameof(OutputAssemblyPath)),
- WinRTProjectionAssemblyPath = GetStringArgument(argsMap, nameof(WinRTProjectionAssemblyPath)),
+ WinRTSdkProjectionAssemblyPath = GetStringArgument(argsMap, nameof(WinRTSdkProjectionAssemblyPath)),
+ WinRTSdkXamlProjectionAssemblyPath = GetNullableStringArgument(argsMap, nameof(WinRTSdkXamlProjectionAssemblyPath)),
+ WinRTProjectionAssemblyPath = GetNullableStringArgument(argsMap, nameof(WinRTProjectionAssemblyPath)),
WinRTComponentAssemblyPath = GetNullableStringArgument(argsMap, nameof(WinRTComponentAssemblyPath)),
GeneratedAssemblyDirectory = GetStringArgument(argsMap, nameof(GeneratedAssemblyDirectory)),
UseWindowsUIXamlProjections = GetBooleanArgument(argsMap, nameof(UseWindowsUIXamlProjections)),
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs
index 391114981..0384a4f8c 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs
@@ -23,9 +23,17 @@ internal sealed partial class InteropGeneratorArgs
[CommandLineArgumentName("--output-assembly-path")]
public required string OutputAssemblyPath { get; init; }
+ /// Gets the path of the WinRT.Sdk.Projection.dll assembly.
+ [CommandLineArgumentName("--winrt-sdk-projection-assembly-path")]
+ public required string WinRTSdkProjectionAssemblyPath { get; init; }
+
+ /// Gets the path of the WinRT.Sdk.Xaml.Projection.dll assembly, if available.
+ [CommandLineArgumentName("--winrt-sdk-xaml-projection-assembly-path")]
+ public string? WinRTSdkXamlProjectionAssemblyPath { get; init; }
+
/// Gets the path of the WinRT.Projection.dll assembly.
[CommandLineArgumentName("--winrt-projection-assembly-path")]
- public required string WinRTProjectionAssemblyPath { get; init; }
+ public string? WinRTProjectionAssemblyPath { get; init; }
/// Gets the path of the WinRT.Component.dll assembly, if available.
[CommandLineArgumentName("--winrt-component-assembly-path")]
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs
index 99e1b3125..feed7e22e 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs
@@ -19,6 +19,12 @@ internal sealed class InteropGeneratorDiscoveryState
/// Backing field for .
private readonly ConcurrentDictionary _moduleDefinitions = [];
+ /// Backing field for .
+ private ModuleDefinition? _winRTSdkProjectionModuleDefinition;
+
+ /// Backing field for .
+ private ModuleDefinition? _winRTSdkXamlProjectionModuleDefinition;
+
/// Backing field for .
private ModuleDefinition? _winRTProjectionModuleDefinition;
@@ -116,6 +122,16 @@ internal sealed class InteropGeneratorDiscoveryState
///
public IReadOnlyDictionary ModuleDefinitions => _moduleDefinitions;
+ ///
+ /// Gets the for WinRT.Sdk.Projection.dll.
+ ///
+ public ModuleDefinition? WinRTSdkProjectionModuleDefinition => _winRTSdkProjectionModuleDefinition;
+
+ ///
+ /// Gets the for WinRT.Sdk.Xaml.Projection.dll.
+ ///
+ public ModuleDefinition? WinRTSdkXamlProjectionModuleDefinition => _winRTSdkXamlProjectionModuleDefinition;
+
///
/// Gets the for WinRT.Projection.dll.
///
@@ -238,6 +254,30 @@ public void TrackModuleDefinition(string path, ModuleDefinition module)
_ = _moduleDefinitions.TryAdd(path, module);
}
+ ///
+ /// Tracks the WinRT.Sdk.Projection.dll loaded module definition.
+ ///
+ /// The loaded module.
+ [MemberNotNull(nameof(_winRTSdkProjectionModuleDefinition))]
+ public void TrackWinRTSdkProjectionModuleDefinition(ModuleDefinition module)
+ {
+ ThrowIfReadOnly();
+
+ _winRTSdkProjectionModuleDefinition = module;
+ }
+
+ ///
+ /// Tracks the WinRT.Sdk.Xaml.Projection.dll loaded module definition.
+ ///
+ /// The loaded module.
+ [MemberNotNull(nameof(_winRTSdkXamlProjectionModuleDefinition))]
+ public void TrackWinRTSdkXamlProjectionModuleDefinition(ModuleDefinition module)
+ {
+ ThrowIfReadOnly();
+
+ _winRTSdkXamlProjectionModuleDefinition = module;
+ }
+
///
/// Tracks the WinRT.Projection.dll loaded module definition.
///
diff --git a/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs b/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs
index 3e163e299..367846a83 100644
--- a/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs
+++ b/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs
@@ -158,12 +158,22 @@ private static bool TryGetIIDFromAttribute(
return true;
}
- // For delegates, try to get the projected type from the projection .dll, as they will have the '[Guid]' attribute on them.
+ // For delegates, try to get the projected type from the right projection .dll, as they will have the '[Guid]' attribute on them.
// These are only needed to generate signatures, so we hide them from the reference assemblies, as they're not useful there.
- if (type.IsDelegate &&
- interopDefinitions.WindowsRuntimeProjectionModule.GetTopLevelTypesLookup().TryGetValue((type.Namespace, type.Name), out TypeDefinition? projectedType))
+ if (type.IsDelegate)
{
- return projectedType.TryGetGuidAttribute(interopReferences, out iid);
+ // Determine the right implementation projection .dll to use for the lookup
+ ModuleDefinition? projectionModule = type.IsProjectedWindowsSdkXamlType
+ ? interopDefinitions.WindowsRuntimeSdkXamlProjectionModule
+ : type.IsProjectedWindowsSdkType
+ ? interopDefinitions.WindowsRuntimeSdkProjectionModule
+ : interopDefinitions.WindowsRuntimeProjectionModule;
+
+ // Try to get the implementation type via a fast lookup, if we did get a valid projection module
+ if (projectionModule?.GetTopLevelTypesLookup().TryGetValue((type.Namespace, type.Name), out TypeDefinition? projectedType) is true)
+ {
+ return projectedType.TryGetGuidAttribute(interopReferences, out iid);
+ }
}
iid = Guid.Empty;
@@ -186,8 +196,15 @@ private static bool TryGetDefaultInterfaceFromAttribute(
InteropReferences interopReferences,
[NotNullWhen(true)] out TypeSignature? defaultInterface)
{
+ // Determine the right implementation projection .dll (see notes above)
+ ModuleDefinition? projectionModule = type.IsProjectedWindowsSdkXamlType
+ ? interopDefinitions.WindowsRuntimeSdkXamlProjectionModule
+ : type.IsProjectedWindowsSdkType
+ ? interopDefinitions.WindowsRuntimeSdkProjectionModule
+ : interopDefinitions.WindowsRuntimeProjectionModule;
+
// Tries to get the projected type from the projection .dll, as it will have the attribute
- if (!interopDefinitions.WindowsRuntimeProjectionModule.GetTopLevelTypesLookup().TryGetValue((type.Namespace, type.Name), out TypeDefinition? projectedType))
+ if (projectionModule?.GetTopLevelTypesLookup().TryGetValue((type.Namespace, type.Name), out TypeDefinition? projectedType) is not true)
{
defaultInterface = null;
diff --git a/src/WinRT.Interop.Generator/References/InteropDefinitions.cs b/src/WinRT.Interop.Generator/References/InteropDefinitions.cs
index 613f88b83..3fb8dd5c3 100644
--- a/src/WinRT.Interop.Generator/References/InteropDefinitions.cs
+++ b/src/WinRT.Interop.Generator/References/InteropDefinitions.cs
@@ -32,25 +32,41 @@ internal sealed class InteropDefinitions
/// Creates a new instance.
///
/// The instance to use.
+ /// The for the Windows Runtime projection assembly for the Windows SDK (i.e. WinRT.Sdk.Projection.dll).
+ /// The for the Windows Runtime projection assembly for the Windows SDK XAML types (i.e. WinRT.Sdk.Xaml.Projection.dll).
/// The for the Windows Runtime projection assembly (i.e. WinRT.Projection.dll).
/// The for the Windows Runtime component assembly (i.e. WinRT.Component.dll).
public InteropDefinitions(
InteropReferences interopReferences,
- ModuleDefinition windowsRuntimeProjectionModule,
+ ModuleDefinition windowsRuntimeSdkProjectionModule,
+ ModuleDefinition? windowsRuntimeSdkXamlProjectionModule,
+ ModuleDefinition? windowsRuntimeProjectionModule,
ModuleDefinition? windowsRuntimeComponentModule)
{
_interopReferences = interopReferences;
_userDefinedInterfaceEntries = [];
_szArrayInterfaceEntries = [];
+ WindowsRuntimeSdkProjectionModule = windowsRuntimeSdkProjectionModule;
+ WindowsRuntimeSdkXamlProjectionModule = windowsRuntimeSdkXamlProjectionModule;
WindowsRuntimeProjectionModule = windowsRuntimeProjectionModule;
WindowsRuntimeComponentModule = windowsRuntimeComponentModule;
}
+ ///
+ /// Gets the for the Windows Runtime projection assembly for the Windows SDK (i.e. WinRT.Sdk.Projection.dll).
+ ///
+ public ModuleDefinition WindowsRuntimeSdkProjectionModule { get; }
+
+ ///
+ /// Gets the for the Windows Runtime projection assembly for the Windows SDK XAML types (i.e. WinRT.Sdk.Xaml.Projection.dll).
+ ///
+ public ModuleDefinition? WindowsRuntimeSdkXamlProjectionModule { get; }
+
///
/// Gets the for the Windows Runtime projection assembly (i.e. WinRT.Projection.dll).
///
- public ModuleDefinition WindowsRuntimeProjectionModule { get; }
+ public ModuleDefinition? WindowsRuntimeProjectionModule { get; }
///
/// Gets the for the Windows Runtime component assembly (i.e. WinRT.Component.dll).
diff --git a/src/WinRT.Interop.Generator/References/InteropNames.cs b/src/WinRT.Interop.Generator/References/InteropNames.cs
index 49293ee8e..805774ff3 100644
--- a/src/WinRT.Interop.Generator/References/InteropNames.cs
+++ b/src/WinRT.Interop.Generator/References/InteropNames.cs
@@ -11,17 +11,27 @@ namespace WindowsRuntime.InteropGenerator.References;
internal static class InteropNames
{
///
- /// The name of the generated interop .dll (i.e. WinRT.Interop.dll).
+ /// The name of the generated interop .dll (i.e. WinRT.Interop.dll).
///
public const string WindowsRuntimeInteropDllName = "WinRT.Interop.dll";
///
- /// The name of the generated projection .dll (i.e. WinRT.Projection.dll).
+ /// The name of the precompiled projection .dll for the Windows SDK (i.e. WinRT.Sdk.Projection.dll).
+ ///
+ public const string WindowsRuntimeSdkProjectionDllName = "WinRT.Sdk.Projection.dll";
+
+ ///
+ /// The name of the precompiled projection .dll for the Windows SDK XAML types (i.e. WinRT.Sdk.Xaml.Projection.dll).
+ ///
+ public const string WindowsRuntimeSdkXamlProjectionDllName = "WinRT.Sdk.Xaml.Projection.dll";
+
+ ///
+ /// The name of the generated projection .dll (i.e. WinRT.Projection.dll).
///
public const string WindowsRuntimeProjectionDllName = "WinRT.Projection.dll";
///
- /// The name of the generated component .dll (i.e. WinRT.Component.dll).
+ /// The name of the generated component .dll (i.e. WinRT.Component.dll).
///
public const string WindowsRuntimeComponentDllName = "WinRT.Component.dll";
@@ -30,6 +40,21 @@ internal static class InteropNames
///
public static ReadOnlySpan WindowsRuntimeInteropAssemblyNameUtf8 => "WinRT.Interop"u8;
+ ///
+ /// The assembly name of the precompiled projection for the Windows SDK (i.e. WinRT.Sdk.Projection).
+ ///
+ public static ReadOnlySpan WindowsRuntimeSdkProjectionAssemblyNameUtf8 => "WinRT.Sdk.Projection"u8;
+
+ ///
+ /// The assembly name of the precompiled projection for the Windows SDK XAML types (i.e. WinRT.Sdk.Xaml.Projection).
+ ///
+ public static ReadOnlySpan WindowsRuntimeSdkXamlProjectionAssemblyNameUtf8 => "WinRT.Sdk.Xaml.Projection"u8;
+
+ ///
+ /// The assembly name of the generated projection (i.e. WinRT.Projection).
+ ///
+ public static ReadOnlySpan WindowsRuntimeProjectionAssemblyNameUtf8 => "WinRT.Projection"u8;
+
///
/// The name of the generated interop .dll (i.e. WinRT.Interop.dll).
///
@@ -45,8 +70,18 @@ internal static class InteropNames
///
public static ReadOnlySpan WindowsSDKDllNameUtf8 => "Microsoft.Windows.SDK.NET.dll"u8;
+ ///
+ /// The assembly name of the Windows SDK projections (i.e. Microsoft.Windows.SDK.NET).
+ ///
+ public static ReadOnlySpan WindowsSDKAssemblyNameUtf8 => "Microsoft.Windows.SDK.NET"u8;
+
///
/// The name of the Windows SDK projections .dll.
///
public static ReadOnlySpan WindowsSDKXamlDllNameUtf8 => "Microsoft.Windows.UI.Xaml.dll"u8;
+
+ ///
+ /// The assembly name of the Windows SDK XAML projections (i.e. Microsoft.Windows.UI.Xaml).
+ ///
+ public static ReadOnlySpan WindowsSDKXamlAssemblyNameUtf8 => "Microsoft.Windows.UI.Xaml"u8;
}
\ No newline at end of file
diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs
index 728f558f0..7e820e96d 100644
--- a/src/WinRT.Interop.Generator/References/InteropReferences.cs
+++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs
@@ -164,12 +164,32 @@ public InteropReferences(
publicKey: false,
publicKeyOrToken: WellKnownPublicKeyTokens.SystemThreading).Import(_corLibTypeFactory.CorLibScope);
+ ///
+ /// Gets the for WinRT.Sdk.Projection.dll.
+ ///
+ ///
+ public AssemblyReference WinRTSdkProjection => field ??= new AssemblyReference(
+ name: InteropNames.WindowsRuntimeSdkProjectionAssemblyNameUtf8,
+ version: new Version(0, 0, 0, 0),
+ publicKey: false,
+ publicKeyOrToken: default).Import(_corLibTypeFactory.CorLibScope);
+
+ ///
+ /// Gets the for WinRT.Sdk.Xaml.Projection.dll.
+ ///
+ ///
+ public AssemblyReference WinRTSdkXamlProjection => field ??= new AssemblyReference(
+ name: InteropNames.WindowsRuntimeSdkXamlProjectionAssemblyNameUtf8,
+ version: new Version(0, 0, 0, 0),
+ publicKey: false,
+ publicKeyOrToken: default).Import(_corLibTypeFactory.CorLibScope);
+
///
/// Gets the for WinRT.Projection.dll.
///
///
public AssemblyReference WinRTProjection => field ??= new AssemblyReference(
- name: "WinRT.Projection"u8,
+ name: InteropNames.WindowsRuntimeProjectionAssemblyNameUtf8,
version: new Version(0, 0, 0, 0),
publicKey: false,
publicKeyOrToken: default).Import(_corLibTypeFactory.CorLibScope);
diff --git a/src/WinRT.Interop.Generator/Resolvers/InteropImplTypeResolver.cs b/src/WinRT.Interop.Generator/Resolvers/InteropImplTypeResolver.cs
index 995151dae..e7288751f 100644
--- a/src/WinRT.Interop.Generator/Resolvers/InteropImplTypeResolver.cs
+++ b/src/WinRT.Interop.Generator/Resolvers/InteropImplTypeResolver.cs
@@ -78,15 +78,22 @@ public static (IMethodDefOrRef get_IID, IMethodDefOrRef get_Vtable) GetProjected
TypeDefinition type,
InteropReferences interopReferences)
{
- // Finally, we have the base scenario of simple non-generic projected Windows Runtime
- // interface types. In this case, the marshalling code will be in the merged projection.
- TypeReference ImplTypeReference = interopReferences.WinRTProjection.CreateTypeReference($"ABI.{type.Namespace}", $"{type.Name}Impl");
+ // Determine the right assembly reference for this projected type
+ AssemblyReference projectionAssembly = type.IsProjectedWindowsSdkXamlType
+ ? interopReferences.WinRTSdkXamlProjection
+ : type.IsProjectedWindowsSdkType
+ ? interopReferences.WinRTSdkProjection
+ : interopReferences.WinRTProjection;
+
+ // Finally, we have the base scenario of simple non-generic projected Windows Runtime interface types.
+ // Those will have the marshalling code in the right implementation projection .dll that we found above.
+ TypeReference ImplTypeReference = projectionAssembly.CreateTypeReference($"ABI.{type.Namespace}", $"{type.Name}Impl");
MemberReference get_VtableMethod = ImplTypeReference.CreateMemberReference("get_Vtable"u8, MethodSignature.CreateStatic(interopReferences.CorLibTypeFactory.IntPtr));
// For normal projected types, the IID is in the generated 'InterfaceIIDs' type in the merged projection
string get_IIDMethodName = $"get_IID_{type.FullName.Replace('.', '_')}";
TypeSignature get_IIDMethodReturnType = WellKnownTypeSignatureFactory.InGuid(interopReferences);
- TypeReference interfaceIIDsTypeReference = interopReferences.WinRTProjection.CreateTypeReference("ABI"u8, "InterfaceIIDs"u8);
+ TypeReference interfaceIIDsTypeReference = projectionAssembly.CreateTypeReference("ABI"u8, "InterfaceIIDs"u8);
MemberReference get_IIDMethod = interfaceIIDsTypeReference.CreateMemberReference(get_IIDMethodName, MethodSignature.CreateStatic(get_IIDMethodReturnType));
// Return the pair of methods from the ABI type in the declaring assembly for the type
diff --git a/src/WinRT.Interop.Generator/Resolvers/InteropMarshallerTypeResolver.cs b/src/WinRT.Interop.Generator/Resolvers/InteropMarshallerTypeResolver.cs
index 65b8c385d..5c22635ce 100644
--- a/src/WinRT.Interop.Generator/Resolvers/InteropMarshallerTypeResolver.cs
+++ b/src/WinRT.Interop.Generator/Resolvers/InteropMarshallerTypeResolver.cs
@@ -68,8 +68,15 @@ public static InteropMarshallerType GetMarshallerType(
}
else
{
- // In all other cases, the marshaller type will be in the merged projection.
- ITypeDefOrRef marshallerType = interopReferences.WinRTProjection.CreateTypeReference(
+ // Determine the right assembly reference for this projected type
+ AssemblyReference projectionAssembly = type.IsProjectedWindowsSdkXamlType
+ ? interopReferences.WinRTSdkXamlProjection
+ : type.IsProjectedWindowsSdkType
+ ? interopReferences.WinRTSdkProjection
+ : interopReferences.WinRTProjection;
+
+ // In all other cases, the marshaller type will be in the right merged projection
+ ITypeDefOrRef marshallerType = projectionAssembly.CreateTypeReference(
ns: $"ABI.{type.Namespace}",
name: $"{type.Name}Marshaller");