diff --git a/nuget/Microsoft.Windows.CsWinRT.CsWinRTGen.targets b/nuget/Microsoft.Windows.CsWinRT.CsWinRTGen.targets
index 0584b2e2b..d2405c128 100644
--- a/nuget/Microsoft.Windows.CsWinRT.CsWinRTGen.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.CsWinRTGen.targets
@@ -155,9 +155,9 @@ Copyright (C) Microsoft Corporation. All rights reserved.
@@ -177,6 +177,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
ReferenceAssemblyPaths="@(_ReferenceAssemblyPaths)"
ImplementationAssemblyPaths="@(ReferencePath)"
OutputAssemblyPath="@(IntermediateAssembly)"
+ WinRTProjectionAssemblyPath="$(_CsWinRTGeneratorMergedProjectionAssemblyPath)"
InteropAssemblyDirectory="$(CsWinRTGeneratorInteropAssemblyDirectory)"
DebugReproDirectory="$(CsWinRTGeneratorDebugReproDirectory)"
CsWinRTToolsDirectory="$(CsWinRTGenEffectiveToolsDirectory)"
diff --git a/src/RunCsWinRTGeneratorTask/RunCsWinRTGenerator.cs b/src/RunCsWinRTGeneratorTask/RunCsWinRTGenerator.cs
index 0aec23905..2cc0240c7 100644
--- a/src/RunCsWinRTGeneratorTask/RunCsWinRTGenerator.cs
+++ b/src/RunCsWinRTGeneratorTask/RunCsWinRTGenerator.cs
@@ -43,6 +43,17 @@ public sealed class RunCsWinRTGenerator : ToolTask
[Required]
public ITaskItem[]? OutputAssemblyPath { get; set; }
+ ///
+ /// Gets or sets the path to the WinRT merged projection assembly.
+ ///
+ [Required]
+ public ITaskItem? WinRTProjectionAssemblyPath { get; set; }
+
+ ///
+ /// Gets or sets the path to the WinRT merged component assembly generated for authoring scenarios.
+ ///
+ public ITaskItem? WinRTComponentAssemblyPath { get; set; }
+
///
/// Gets or sets the directory where the generated interop assembly will be placed.
///
@@ -149,6 +160,13 @@ protected override bool ValidateParameters()
return false;
}
+ if (WinRTProjectionAssemblyPath is null)
+ {
+ Log.LogWarning("Invalid 'WinRTProjectionAssemblyPath' input.");
+
+ return false;
+ }
+
if (InteropAssemblyDirectory is null || !Directory.Exists(InteropAssemblyDirectory))
{
Log.LogWarning("Generated assembly directory '{0}' is invalid or does not exist.", InteropAssemblyDirectory);
@@ -236,6 +254,8 @@ 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);
+ AppendResponseFileOptionalCommand(args, "--winrt-component-assembly-path", WinRTComponentAssemblyPath?.ItemSpec);
AppendResponseFileCommand(args, "--generated-assembly-directory", InteropAssemblyDirectory!);
AppendResponseFileOptionalCommand(args, "--debug-repro-directory", DebugReproDirectory);
AppendResponseFileCommand(args, "--use-windows-ui-xaml-projections", UseWindowsUIXamlProjections.ToString());
diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs
index 81fd596ef..3cd937e73 100644
--- a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs
+++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs
@@ -20,11 +20,13 @@ public static class ICommand
///
/// Creates a new type definition for the interface implementation of the interface.
///
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
/// The resulting interface implementation type.
public static void InterfaceImpl(
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -42,7 +44,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(interfaceType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(interfaceType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces = { new InterfaceImplementation(interfaceType.ToTypeDefOrRef()) }
};
diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs
index 1d0da3b11..3af1f9f51 100644
--- a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs
+++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs
@@ -20,11 +20,13 @@ public static class INotifyCollectionChanged
///
/// Creates a new type definition for the interface implementation of the interface.
///
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
/// The resulting interface implementation type.
public static void InterfaceImpl(
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -42,7 +44,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(interfaceType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(interfaceType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces = { new InterfaceImplementation(interfaceType.ToTypeDefOrRef()) }
};
diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs
index a42e81432..4dfd2169b 100644
--- a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs
+++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs
@@ -20,11 +20,13 @@ public static class INotifyPropertyChanged
///
/// Creates a new type definition for the interface implementation of the interface.
///
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
/// The resulting interface implementation type.
public static void InterfaceImpl(
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -42,7 +44,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(interfaceType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(interfaceType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces = { new InterfaceImplementation(interfaceType.ToTypeDefOrRef()) }
};
diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs
index 189e28a93..f7f08b1f1 100644
--- a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs
+++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs
@@ -25,10 +25,12 @@ internal static partial class DynamicCustomMappedTypeMapEntriesBuilder
/// Defines all assembly attributes for dynamic custom-mapped type map entries.
///
/// The arguments for this invocation.
+ /// The instance to use.
/// The instance to use.
/// The interop module being built.
public static void AssemblyAttributes(
InteropGeneratorArgs args,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module)
{
@@ -60,16 +62,19 @@ public static void AssemblyAttributes(
useComWrappersMarshallerAttribute: true);
ICommandInterfaceType(
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections);
INotifyCollectionChangedInterfaceType(
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections);
INotifyPropertyChangedInterfaceType(
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections);
@@ -185,10 +190,12 @@ private static void InterfaceType(
///
/// Creates a new custom attribute value for for the interface type.
///
+ /// The instance to use.
/// The instance to use.
/// The module that the attribute will be used from.
/// Whether to use Windows.UI.Xaml projections.
private static void ICommandInterfaceType(
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections)
@@ -215,6 +222,7 @@ private static void ICommandInterfaceType(
// Define the 'InterfaceImpl' type for the 'ICommand' interface type
ICommand.InterfaceImpl(
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
@@ -239,10 +247,12 @@ private static void ICommandInterfaceType(
///
/// Creates a new custom attribute value for for the interface type.
///
+ /// The instance to use.
/// The instance to use.
/// The module that the attribute will be used from.
/// Whether to use Windows.UI.Xaml projections.
private static void INotifyCollectionChangedInterfaceType(
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections)
@@ -269,6 +279,7 @@ private static void INotifyCollectionChangedInterfaceType(
// Define the 'InterfaceImpl' type for the 'INotifyCollectionChanged' interface type
INotifyCollectionChanged.InterfaceImpl(
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
@@ -293,10 +304,12 @@ private static void INotifyCollectionChangedInterfaceType(
///
/// Creates a new custom attribute value for for the interface type.
///
+ /// The instance to use.
/// The instance to use.
/// The module that the attribute will be used from.
/// Whether to use Windows.UI.Xaml projections.
private static void INotifyPropertyChangedInterfaceType(
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections)
@@ -323,6 +336,7 @@ private static void INotifyPropertyChangedInterfaceType(
// Define the 'InterfaceImpl' type for the 'INotifyPropertyChanged' interface type
INotifyPropertyChanged.InterfaceImpl(
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs
index c7732764c..29754cd24 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs
@@ -45,7 +45,7 @@ public static void IIDs(
name: InteropUtf8NameFactory.TypeName(delegateType),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
- iid: GuidGenerator.CreateIID(delegateType, interopReferences, useWindowsUIXamlProjections),
+ iid: GuidGenerator.CreateIID(delegateType, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
out get_IidMethod);
// 'IReference' IID, which uses a boxed type signature to represent it.
@@ -58,7 +58,7 @@ public static void IIDs(
name: InteropUtf8NameFactory.TypeName(delegateType, "Reference"),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
- iid: GuidGenerator.CreateIID(delegateType.MakeBoxedType(), interopReferences, useWindowsUIXamlProjections),
+ iid: GuidGenerator.CreateIID(delegateType.MakeBoxedType(), interopDefinitions, interopReferences, useWindowsUIXamlProjections),
out get_ReferenceIidMethod);
}
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncActionWithProgress1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncActionWithProgress1.cs
index c4dcebaf9..28dfd40f0 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncActionWithProgress1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncActionWithProgress1.cs
@@ -231,6 +231,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the async action type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -238,6 +239,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature actionType,
TypeDefinition actionMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -255,7 +257,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(actionType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(actionType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperation1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperation1.cs
index 036fd539b..5b2b91cd3 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperation1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperation1.cs
@@ -185,6 +185,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the async operation type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -192,6 +193,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature operationType,
TypeDefinition operationMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -209,7 +211,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(operationType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(operationType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperationWithProgress2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperationWithProgress2.cs
index 22e336f03..ffdf9de7e 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperationWithProgress2.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IAsyncOperationWithProgress2.cs
@@ -225,6 +225,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the async operation type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -232,6 +233,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature operationType,
TypeDefinition operationMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -250,7 +252,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(operationType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(operationType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs
index 4841043e6..a2733e146 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IDictionary2.cs
@@ -687,6 +687,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -694,6 +695,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature dictionaryType,
TypeDefinition dictionaryMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -715,7 +717,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(dictionaryType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(dictionaryType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerable1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerable1.cs
index 79b61b694..076be53f1 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerable1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerable1.cs
@@ -341,6 +341,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -348,6 +349,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature enumerableType,
TypeDefinition iterableMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -365,7 +367,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(enumerableType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(enumerableType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerator1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerator1.cs
index efb9172fd..41cc1f4ce 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerator1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IEnumerator1.cs
@@ -44,7 +44,7 @@ public static void IID(
name: InteropUtf8NameFactory.TypeName(enumeratorType),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
- iid: GuidGenerator.CreateIID(enumeratorType, interopReferences, useWindowsUIXamlProjections),
+ iid: GuidGenerator.CreateIID(enumeratorType, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
out get_IidMethod);
// Track the IID method, as it's needed to marshal enumerators from the 'IIterable.First' implementation
@@ -360,6 +360,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -367,6 +368,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature enumeratorType,
TypeDefinition iteratorMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -384,7 +386,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(enumeratorType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(enumeratorType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs
index e47d82985..a7d654252 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs
@@ -612,6 +612,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -619,6 +620,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature listType,
TypeDefinition listMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -638,7 +640,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(listType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(listType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IMapChangedEventArgs1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IMapChangedEventArgs1.cs
index 3c57d3c18..14c3c7f17 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IMapChangedEventArgs1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IMapChangedEventArgs1.cs
@@ -173,6 +173,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the args type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -180,6 +181,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature argsType,
TypeDefinition argsMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -197,7 +199,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(argsType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(argsType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces = { new InterfaceImplementation(argsType.ToTypeDefOrRef()) }
};
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableMap2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableMap2.cs
index 143fc4ddf..3e99bbbc7 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableMap2.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableMap2.cs
@@ -301,6 +301,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the map type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -308,6 +309,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature mapType,
TypeDefinition mapMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -332,7 +334,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(mapType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(mapType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableVector1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableVector1.cs
index 4d2b13076..8bca73702 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableVector1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IObservableVector1.cs
@@ -296,6 +296,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the vector type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -303,6 +304,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature vectorType,
TypeDefinition vectorMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -320,7 +322,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(vectorType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(vectorType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs
index db114d164..0e60639f9 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyDictionary2.cs
@@ -374,6 +374,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -381,6 +382,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature readOnlyDictionaryType,
TypeDefinition readOnlyDictionaryMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -402,7 +404,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(readOnlyDictionaryType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(readOnlyDictionaryType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs
index 9246bb4c1..d9c44335f 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs
@@ -277,6 +277,7 @@ public static void ComWrappersMarshallerAttribute(
///
/// The for the type.
/// The instance returned by .
+ /// The instance to use.
/// The instance to use.
/// The module that will contain the type being created.
/// Whether to use Windows.UI.Xaml projections.
@@ -284,6 +285,7 @@ public static void ComWrappersMarshallerAttribute(
public static void InterfaceImpl(
GenericInstanceTypeSignature readOnlyListType,
TypeDefinition readOnlyListMethodsType,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module,
bool useWindowsUIXamlProjections,
@@ -303,7 +305,7 @@ public static void InterfaceImpl(
CustomAttributes =
{
new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor),
- InteropCustomAttributeFactory.Guid(readOnlyListType, interopReferences, useWindowsUIXamlProjections)
+ InteropCustomAttributeFactory.Guid(readOnlyListType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)
},
Interfaces =
{
diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs
index 29137981b..44c46aa2a 100644
--- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs
+++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs
@@ -45,7 +45,7 @@ public static void IID(
name: InteropUtf8NameFactory.TypeName(interfaceType),
interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
- iid: GuidGenerator.CreateIID(interfaceType, interopReferences, useWindowsUIXamlProjections),
+ iid: GuidGenerator.CreateIID(interfaceType, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
out get_IidMethod);
}
diff --git a/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs b/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs
index 4ac565d91..accbcdc5a 100644
--- a/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs
+++ b/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs
@@ -722,6 +722,30 @@ public static WellKnownInteropWarning ExceededNumberOfExposedWindowsRuntimeInter
return Warning(84, $"Exposed type '{type}' exceeded the maximum limit of 128 projected Windows Runtime interfaces implemented: all exceeding interfaces will not be included in the set of available COM interface entries.");
}
+ ///
+ /// Invalid reference to a reserved .dll name.
+ ///
+ public static WellKnownInteropException ReservedDllNameReferenceError(string dllName)
+ {
+ return Exception(85, $"Invalid .dll reference to the reserved .dll name '{dllName}': it is not valid to reference .dll-s with a name starting with the 'WinRT.' prefix.");
+ }
+
+ ///
+ /// Mismatched path for a reserved .dll file.
+ ///
+ public static WellKnownInteropException ReservedDllOriginalPathMismatch(string dllName)
+ {
+ return Exception(86, $"The reserved '{dllName}' assembly has a mismatching path with the item supplied via '$(ReferencePath)'.");
+ }
+
+ ///
+ /// Mismatched path for a reserved .dll file.
+ ///
+ public static WellKnownInteropException ReservedDllOriginalPathMismatchFromDebugRepro(string dllName)
+ {
+ return Exception(87, $"The reserved '{dllName}' assembly has a mismatching path with the item supplied via '$(ReferencePath)': the debug repro canot be generated.");
+ }
+
///
/// Creates a new exception with the specified id and message.
///
diff --git a/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.TypesLookup.cs b/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.TypesLookup.cs
new file mode 100644
index 000000000..cce095090
--- /dev/null
+++ b/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.TypesLookup.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Frozen;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using AsmResolver;
+using AsmResolver.DotNet;
+
+namespace WindowsRuntime.InteropGenerator;
+
+///
+internal partial class ModuleDefinitionExtensions
+{
+ ///
+ /// Gets a lookup of top level types for a given module.
+ ///
+ /// The input instance.
+ /// The resulting top level types lookup.
+ public static IReadOnlyDictionary<(Utf8String? Namespace, Utf8String? Name), TypeDefinition> GetTopLevelTypesLookup(this ModuleDefinition module)
+ {
+ return TopLevelTypesLookupCache.Instance.GetOrAdd(
+ key: module,
+ valueFactory: static module => module.TopLevelTypes.ToFrozenDictionary(static type => (type.Namespace, type.Name)));
+ }
+}
+
+///
+/// Contains a shared cache of top level types lookups, to speed up search operations.
+///
+file static class TopLevelTypesLookupCache
+{
+ ///
+ /// The singleton top level types lookups map.
+ ///
+ public static readonly ConditionalWeakTable> Instance = [];
+}
\ No newline at end of file
diff --git a/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.cs b/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.cs
index 85c80c7fd..e4a8fba78 100644
--- a/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.cs
+++ b/src/WinRT.Interop.Generator/Extensions/ModuleDefinitionExtensions.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using AsmResolver;
using AsmResolver.DotNet;
@@ -16,7 +17,7 @@ namespace WindowsRuntime.InteropGenerator;
///
/// Extensions for the type.
///
-internal static class ModuleDefinitionExtensions
+internal static partial class ModuleDefinitionExtensions
{
///
/// Gets the first type with a given namespace and name from the specified type.
@@ -28,15 +29,34 @@ internal static class ModuleDefinitionExtensions
/// Thrown if the type couldn't be found.
public static TypeDefinition GetType(this ModuleDefinition module, Utf8String ns, Utf8String name)
{
- foreach (TypeDefinition type in module.TopLevelTypes)
+ return TryGetType(module, ns, name, out TypeDefinition? type)
+ ? type
+ : throw new ArgumentException($"Type with name '{ns}.{name}' not found.");
+ }
+
+ ///
+ /// Tries to get the first type with a given namespace and name from the specified type.
+ ///
+ /// The input instance.
+ /// The namespace of the type.
+ /// The name of the type to get.
+ /// The resulting type, if found.
+ /// Whether was found.
+ public static bool TryGetType(this ModuleDefinition module, Utf8String? ns, Utf8String? name, [NotNullWhen(true)] out TypeDefinition? type)
+ {
+ foreach (TypeDefinition item in module.TopLevelTypes)
{
- if (type.Namespace == ns && type.Name == name)
+ if (item.Namespace == ns && item.Name == name)
{
- return type;
+ type = item;
+
+ return true;
}
}
- throw new ArgumentException($"Type with name '{ns}.{name}' not found.");
+ type = null;
+
+ return false;
}
///
diff --git a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs
index 43cac0eb8..dc1eaef87 100644
--- a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs
+++ b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs
@@ -31,12 +31,18 @@ internal static class WindowsRuntimeExtensions
/// Whether the module represents a Windows Runtime reference assembly.
public bool IsWindowsRuntimeReferenceAssembly => member.HasCustomAttribute(WellKnownMetadataNames.WindowsRuntimeInteropServices, WellKnownMetadataNames.WindowsRuntimeReferenceAssemblyAttribute);
+ ///
+ /// Checks whether a (expected to be an ) represents a Windows Runtime component assembly.
+ ///
+ /// Whether the module represents a Windows Runtime component assembly.
+ public bool IsWindowsRuntimeComponentAssembly => member.HasCustomAttribute(WellKnownMetadataNames.WindowsRuntimeInteropServices, WellKnownMetadataNames.WindowsRuntimeComponentAssemblyAttribute);
+
///
/// Attempts to retrieve the IID from the applied to the specified metadata member.
///
/// The instance to use.
/// The resulting value, if found.
- /// Whether was succesfully retrieved.
+ /// Whether was successfully retrieved.
public bool TryGetGuidAttribute(InteropReferences interopReferences, out Guid iid)
{
if (member.TryGetCustomAttribute(interopReferences.GuidAttribute, out CustomAttribute? customAttribute))
@@ -1107,4 +1113,9 @@ file static class WellKnownMetadataNames
/// The "WindowsRuntimeReferenceAssemblyAttribute" text.
///
public static readonly Utf8String WindowsRuntimeReferenceAssemblyAttribute = "WindowsRuntimeReferenceAssemblyAttribute"u8;
+
+ ///
+ /// The "WindowsRuntimeComponentAssemblyAttribute" text.
+ ///
+ public static readonly Utf8String WindowsRuntimeComponentAssemblyAttribute = "WindowsRuntimeComponentAssemblyAttribute"u8;
}
\ No newline at end of file
diff --git a/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs b/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs
index 949adcfd3..7cc518bc9 100644
--- a/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs
+++ b/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs
@@ -20,16 +20,18 @@ internal static class InteropCustomAttributeFactory
/// Creates a new custom attribute value for (and imports all metadata elements for it).
///
/// The type to generate the IID for.
+ /// The instance to use.
/// The instance to use.
/// Whether to use Windows.UI.Xaml projections.
/// The resulting value.
public static CustomAttribute Guid(
TypeSignature type,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
bool useWindowsUIXamlProjections)
{
return Guid(
- guid: GuidGenerator.CreateIID(type, interopReferences, useWindowsUIXamlProjections),
+ guid: GuidGenerator.CreateIID(type, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
interopReferences: interopReferences);
}
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs
index cf9ab4ed1..46190c7fd 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.DebugRepro.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Compression;
using System.Linq;
@@ -68,6 +69,8 @@ private static string UnpackDebugRepro(string path, CancellationToken token)
List referencePaths = [];
List implementationPaths = [];
string? outputAssemblyPath = null;
+ string? winRTProjectionAssemblyHashedName = null;
+ string? winRTComponentAssemblyHashedName = null;
// Create another subdirectory for all the input assembly paths. We don't put these in the top level
// temporary folder so that the number of files there remains very small. The reason is just to
@@ -104,6 +107,16 @@ private static string UnpackDebugRepro(string path, CancellationToken token)
{
implementationPaths.Add(destinationPath);
}
+
+ // Also track the private implementation detail .dll-s (these are also in the set of references)
+ if (dllEntry.Name == args.WinRTProjectionAssemblyPath)
+ {
+ winRTProjectionAssemblyHashedName = destinationPath;
+ }
+ else if (args.WinRTComponentAssemblyPath is not null && dllEntry.Name == args.WinRTComponentAssemblyPath)
+ {
+ winRTComponentAssemblyHashedName = destinationPath;
+ }
}
token.ThrowIfCancellationRequested();
@@ -114,6 +127,8 @@ private static string UnpackDebugRepro(string path, CancellationToken token)
ReferenceAssemblyPaths = [.. referencePaths],
ImplementationAssemblyPaths = [.. implementationPaths],
OutputAssemblyPath = outputAssemblyPath!,
+ WinRTProjectionAssemblyPath = winRTProjectionAssemblyHashedName!,
+ WinRTComponentAssemblyPath = winRTComponentAssemblyHashedName,
GeneratedAssemblyDirectory = tempDirectory,
UseWindowsUIXamlProjections = args.UseWindowsUIXamlProjections,
ValidateWinRTRuntimeAssemblyVersion = args.ValidateWinRTRuntimeAssemblyVersion,
@@ -175,22 +190,21 @@ private static void SaveDebugRepro(InteropGeneratorArgs args)
args.Token.ThrowIfCancellationRequested();
- // Add the output assembly to the temporary directory with a hashed name
- string outputAssemblyHashedName = GetHashedFileName(args.OutputAssemblyPath);
- string outputAssemblyDestination = Path.Combine(tempDirectory, outputAssemblyHashedName);
-
- File.Copy(args.OutputAssemblyPath, outputAssemblyDestination, overwrite: true);
+ // Hash and copy the well known assemblies we use as input
+ string outputAssemblyHashedName = CopyHashedFileToDirectory(args.OutputAssemblyPath, tempDirectory, originalPaths, args.Token);
+ string winRTProjectionAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTProjectionAssemblyPath, tempDirectory, originalPaths, args.Token);
+ string? winRTComponentAssemblyHashedName = CopyHashedFileToDirectory(args.WinRTComponentAssemblyPath, tempDirectory, originalPaths, args.Token);
args.Token.ThrowIfCancellationRequested();
- originalPaths.Add(outputAssemblyHashedName, args.OutputAssemblyPath);
-
// Prepare the .rsp file with all updated arguments
string rspText = new InteropGeneratorArgs
{
ReferenceAssemblyPaths = [.. updatedReferenceDllNames],
ImplementationAssemblyPaths = [.. updatedImplementationDllNames],
OutputAssemblyPath = outputAssemblyHashedName,
+ WinRTProjectionAssemblyPath = winRTProjectionAssemblyHashedName,
+ WinRTComponentAssemblyPath = winRTComponentAssemblyHashedName,
GeneratedAssemblyDirectory = args.GeneratedAssemblyDirectory,
UseWindowsUIXamlProjections = args.UseWindowsUIXamlProjections,
ValidateWinRTRuntimeAssemblyVersion = args.ValidateWinRTRuntimeAssemblyVersion,
@@ -279,4 +293,57 @@ private static List CopyHashedFilesToDirectory(
return updatedDllNames;
}
+
+ ///
+ /// Copies a specified assembly to a target folder.
+ ///
+ /// The input assembly paths.
+ /// The target directory to copy the assembly to.
+ /// A dictionary to store the original paths of the copied assemblies.
+ /// A cancellation token to monitor for cancellation requests.
+ /// The hashed filename.
+ [return: NotNullIfNotNull(nameof(assemblyPath))]
+ private static string? CopyHashedFileToDirectory(
+ string? assemblyPath,
+ string destinationDirectory,
+ Dictionary originalPaths,
+ CancellationToken token)
+ {
+ if (assemblyPath is null)
+ {
+ return null;
+ }
+
+ string hashedName = GetHashedFileName(assemblyPath);
+
+ // Special case for private implementation detail assemblies (e.g. 'WinRT.Projection.dll') that are
+ // both passed via the reference set, but also explicitly as separate properties. In that case, we
+ // expect that those should already be in the original paths at this point. So we validate that
+ // the path actually matches, and simply do nothing if that's the case, as this is intended.
+ if (originalPaths.TryGetValue(hashedName, out string? originalPath) && originalPath == assemblyPath)
+ {
+ return hashedName;
+ }
+
+ // If we get to this point, it means that either a private implementation assembly was passed with a
+ // different path than the one provided to the reference set, which should never happen (it's invalid).
+ if (originalPaths.ContainsKey(hashedName))
+ {
+ string fileName = Path.GetFileName(Path.Normalize(assemblyPath));
+
+ throw WellKnownInteropExceptions.ReservedDllOriginalPathMismatchFromDebugRepro(fileName);
+ }
+
+ string destinationPath = Path.Combine(destinationDirectory, hashedName);
+
+ // After validating that the file is unique and should be copied, we can safely do that. We move
+ // this operation to ensure we don't accidentally end up with duplicated .dll-s in the debug repro.
+ File.Copy(assemblyPath, destinationPath, overwrite: true);
+
+ token.ThrowIfCancellationRequested();
+
+ originalPaths.Add(hashedName, assemblyPath);
+
+ return hashedName;
+ }
}
\ No newline at end of file
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs
index e289bff12..5989a9b53 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Discover.cs
@@ -40,6 +40,10 @@ 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.
+ LoadWinRTModules(args, discoveryState);
+
try
{
// Load and process all modules, potentially in parallel
@@ -75,6 +79,29 @@ private static InteropGeneratorDiscoveryState Discover(InteropGeneratorArgs args
return discoveryState;
}
+ ///
+ /// Loads the special WinRT module definitions.
+ ///
+ /// The arguments for this invocation.
+ /// 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);
+
+ discoveryState.TrackWinRTProjectionModuleDefinition(winRTProjectionModule);
+
+ args.Token.ThrowIfCancellationRequested();
+
+ // Load the 'WinRT.Component.dll' module, if available
+ if (args.WinRTComponentAssemblyPath is not null)
+ {
+ ModuleDefinition winRTComponentModule = ModuleDefinition.FromFile(args.WinRTComponentAssemblyPath, ((PathAssemblyResolver)discoveryState.AssemblyResolver).ReaderParameters);
+
+ discoveryState.TrackWinRTComponentModuleDefinition(winRTComponentModule);
+ }
+ }
+
///
/// Loads and processes a module definition.
///
@@ -86,6 +113,33 @@ private static void LoadAndProcessModule(
InteropGeneratorDiscoveryState discoveryState,
string path)
{
+ ReadOnlySpan fileName = Path.GetFileName(path.AsSpan());
+
+ // Validate that the two possible private implementation detail .dll-s we expect have a matching path. These are:
+ // - '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) ||
+ (fileName.SequenceEqual(InteropNames.WindowsRuntimeComponentDllName) && path != args.WinRTComponentAssemblyPath))
+ {
+ throw WellKnownInteropExceptions.ReservedDllOriginalPathMismatch(fileName.ToString());
+ }
+
+ // 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) ||
+ fileName.SequenceEqual(InteropNames.WindowsRuntimeComponentDllName))
+ {
+ return;
+ }
+
+ // Validate that the reserved 'WinRT.Interop.dll' is not passed as input. This is the .dll that this tool is generating,
+ // so for it to already exist and be passed as input would always be invalid (and would indicate some kind of build issue).
+ if (fileName.SequenceEqual(InteropNames.WindowsRuntimeInteropDllName))
+ {
+ throw WellKnownInteropExceptions.ReservedDllNameReferenceError(fileName.ToString());
+ }
+
ModuleDefinition module;
// Try to load the .dll at the current path
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs
index 629f286c7..30def2216 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs
@@ -45,7 +45,10 @@ private static void Emit(InteropGeneratorArgs args, InteropGeneratorDiscoverySta
// Setup the well known items to use when emitting code
InteropReferences interopReferences = new(module.CorLibTypeFactory, windowsRuntimeModule, windowsFoundationModule);
- InteropDefinitions interopDefinitions = new(interopReferences);
+ InteropDefinitions interopDefinitions = new(
+ interopReferences: interopReferences,
+ windowsRuntimeProjectionModule: discoveryState.WinRTProjectionModuleDefinition!,
+ windowsRuntimeComponentModule: discoveryState.WinRTComponentModuleDefinition);
args.Token.ThrowIfCancellationRequested();
@@ -171,7 +174,7 @@ private static void Emit(InteropGeneratorArgs args, InteropGeneratorDiscoverySta
args.Token.ThrowIfCancellationRequested();
// Add all dynamic type map entries for custom-mapped types
- DefineDynamicCustomMappedTypeMapEntries(args, interopReferences, module);
+ DefineDynamicCustomMappedTypeMapEntries(args, interopDefinitions, interopReferences, module);
args.Token.ThrowIfCancellationRequested();
@@ -238,7 +241,7 @@ private static ModuleDefinition DefineInteropModule(
try
{
// Create the module for the 'WinRT.Interop.dll' assembly, where we'll add all generated types to
- ModuleDefinition winRTInteropModule = new(InteropNames.InteropDllNameUtf8, assemblyModule.OriginalTargetRuntime.GetDefaultCorLib())
+ ModuleDefinition winRTInteropModule = new(InteropNames.WindowsRuntimeInteropDllNameUtf8, assemblyModule.OriginalTargetRuntime.GetDefaultCorLib())
{
// Create and set a metadata resolver from the assembly resolver that we created during the discovery phase (used for auto-import)
MetadataResolver = new DefaultMetadataResolver(discoveryState.AssemblyResolver),
@@ -250,7 +253,7 @@ private static ModuleDefinition DefineInteropModule(
// Also create a containing assembly for it (needed for the emit phase). We don't actually need the assembly
// ourselves, but creating it and adding the module will update the declaring assembly for types added to it.
- _ = new AssemblyDefinition(InteropNames.InteropAssemblyNameUtf8, assemblyModule.Assembly?.Version ?? new Version(0, 0, 0, 0))
+ _ = new AssemblyDefinition(InteropNames.WindowsRuntimeInteropAssemblyNameUtf8, assemblyModule.Assembly?.Version ?? new Version(0, 0, 0, 0))
{
Modules = { winRTInteropModule }
};
@@ -525,6 +528,7 @@ private static void DefineIEnumeratorTypes(
InteropTypeDefinitionBuilder.IEnumerator1.InterfaceImpl(
enumeratorType: typeSignature,
iteratorMethodsType: iteratorMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -650,6 +654,7 @@ private static void DefineIEnumerableTypes(
InteropTypeDefinitionBuilder.IEnumerable1.InterfaceImpl(
enumerableType: typeSignature,
iterableMethodsType: iterableMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -777,6 +782,7 @@ private static void DefineIReadOnlyListTypes(
InteropTypeDefinitionBuilder.IReadOnlyList1.InterfaceImpl(
readOnlyListType: typeSignature,
readOnlyListMethodsType: readOnlyListMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -912,6 +918,7 @@ private static void DefineIListTypes(
InteropTypeDefinitionBuilder.IList1.InterfaceImpl(
listType: typeSignature,
listMethodsType: listMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1040,6 +1047,7 @@ private static void DefineIReadOnlyDictionaryTypes(
InteropTypeDefinitionBuilder.IReadOnlyDictionary2.InterfaceImpl(
readOnlyDictionaryType: typeSignature,
readOnlyDictionaryMethodsType: readOnlyDictionaryMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1176,6 +1184,7 @@ private static void DefineIDictionaryTypes(
InteropTypeDefinitionBuilder.IDictionary2.InterfaceImpl(
dictionaryType: typeSignature,
dictionaryMethodsType: dictionaryMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1400,6 +1409,7 @@ private static void DefineIMapChangedEventArgsTypes(
InteropTypeDefinitionBuilder.IMapChangedEventArgs1.InterfaceImpl(
argsType: typeSignature,
argsMethodsType: argsMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1517,6 +1527,7 @@ private static void DefineIObservableVectorTypes(
InteropTypeDefinitionBuilder.IObservableVector1.InterfaceImpl(
vectorType: typeSignature,
vectorMethodsType: methodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1634,6 +1645,7 @@ private static void DefineIObservableMapTypes(
InteropTypeDefinitionBuilder.IObservableMap2.InterfaceImpl(
mapType: typeSignature,
mapMethodsType: methodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1744,6 +1756,7 @@ private static void DefineIAsyncActionWithProgressTypes(
InteropTypeDefinitionBuilder.IAsyncActionWithProgress1.InterfaceImpl(
actionType: typeSignature,
actionMethodsType: actionMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1854,6 +1867,7 @@ private static void DefineIAsyncOperationTypes(
InteropTypeDefinitionBuilder.IAsyncOperation1.InterfaceImpl(
operationType: typeSignature,
operationMethodsType: operationMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -1964,6 +1978,7 @@ private static void DefineIAsyncOperationWithProgressTypes(
InteropTypeDefinitionBuilder.IAsyncOperationWithProgress2.InterfaceImpl(
operationType: typeSignature,
operationMethodsType: operationMethodsType,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module,
useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections,
@@ -2514,10 +2529,12 @@ private static void DefineDynamicImplementationDetailTypes(InteropDefinitions in
/// Defines the dynamic type map entries for custom-mapped types.
///
///
+ /// The instance to use.
/// The instance to use.
/// The interop module being built.
private static void DefineDynamicCustomMappedTypeMapEntries(
InteropGeneratorArgs args,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
ModuleDefinition module)
{
@@ -2525,6 +2542,7 @@ private static void DefineDynamicCustomMappedTypeMapEntries(
{
DynamicCustomMappedTypeMapEntriesBuilder.AssemblyAttributes(
args: args,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
module: module);
}
@@ -2589,7 +2607,7 @@ private static void EmitMetadataAssemblyAttributes(InteropReferences interopRefe
/// The module to write to disk.
private static void WriteInteropModuleToDisk(InteropGeneratorArgs args, ModuleDefinition module)
{
- string winRTInteropAssemblyPath = Path.Combine(args.GeneratedAssemblyDirectory, InteropNames.InteropDllName);
+ string winRTInteropAssemblyPath = Path.Combine(args.GeneratedAssemblyDirectory, InteropNames.WindowsRuntimeInteropDllName);
try
{
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.cs
index fb787250b..05471dccb 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.cs
@@ -115,6 +115,6 @@ public static void Run([Argument] string inputFilePath, CancellationToken token)
}
// Notify the user that generation was successful
- ConsoleApp.Log($"Interop code generated -> {Path.Combine(args.GeneratedAssemblyDirectory, InteropNames.InteropDllName)}");
+ ConsoleApp.Log($"Interop code generated -> {Path.Combine(args.GeneratedAssemblyDirectory, InteropNames.WindowsRuntimeInteropDllName)}");
}
}
\ No newline at end of file
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs
index c0ac96f03..85d79fe34 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Formatting.cs
@@ -28,6 +28,17 @@ public string FormatToResponseFile()
_ = builder.Append(' ');
_ = builder.AppendLine(OutputAssemblyPath);
+ _ = builder.Append(GetCommandLineArgumentName(nameof(WinRTProjectionAssemblyPath)));
+ _ = builder.Append(' ');
+ _ = builder.AppendLine(WinRTProjectionAssemblyPath);
+
+ if (WinRTComponentAssemblyPath is not null)
+ {
+ _ = builder.Append(GetCommandLineArgumentName(nameof(WinRTComponentAssemblyPath)));
+ _ = builder.Append(' ');
+ _ = builder.AppendLine(WinRTComponentAssemblyPath);
+ }
+
_ = builder.Append(GetCommandLineArgumentName(nameof(GeneratedAssemblyDirectory)));
_ = builder.Append(' ');
_ = builder.AppendLine(GeneratedAssemblyDirectory);
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs
index ed1f2507e..9ebe6070e 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.Parsing.cs
@@ -100,6 +100,8 @@ 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)),
+ WinRTComponentAssemblyPath = GetNullableStringArgument(argsMap, nameof(WinRTComponentAssemblyPath)),
GeneratedAssemblyDirectory = GetStringArgument(argsMap, nameof(GeneratedAssemblyDirectory)),
UseWindowsUIXamlProjections = GetBooleanArgument(argsMap, nameof(UseWindowsUIXamlProjections)),
ValidateWinRTRuntimeAssemblyVersion = GetBooleanArgument(argsMap, nameof(ValidateWinRTRuntimeAssemblyVersion)),
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs
index f0be421cd..9f2045709 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorArgs.cs
@@ -23,6 +23,14 @@ internal sealed partial class InteropGeneratorArgs
[CommandLineArgumentName("--output-assembly-path")]
public required string OutputAssemblyPath { get; init; }
+ /// Gets the path of the WinRT.Projection.dll assembly.
+ [CommandLineArgumentName("--winrt-projection-assembly-path")]
+ public required string WinRTProjectionAssemblyPath { get; init; }
+
+ /// Gets the path of the WinRT.Component.dll assembly, if available.
+ [CommandLineArgumentName("--winrt-component-assembly-path")]
+ public string? WinRTComponentAssemblyPath { get; init; }
+
/// Gets the directory to use to place the generated assembly.
[CommandLineArgumentName("--generated-assembly-directory")]
public required string GeneratedAssemblyDirectory { get; init; }
diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs
index 5fbfdabe2..99e1b3125 100644
--- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs
+++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorDiscoveryState.cs
@@ -3,6 +3,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
using WindowsRuntime.InteropGenerator.Errors;
@@ -18,6 +19,12 @@ internal sealed class InteropGeneratorDiscoveryState
/// Backing field for .
private readonly ConcurrentDictionary _moduleDefinitions = [];
+ /// Backing field for .
+ private ModuleDefinition? _winRTProjectionModuleDefinition;
+
+ /// Backing field for .
+ private ModuleDefinition? _winRTComponentModuleDefinition;
+
/// Backing field for .
private readonly ConcurrentDictionary _typeHierarchyEntries = [];
@@ -109,6 +116,16 @@ internal sealed class InteropGeneratorDiscoveryState
///
public IReadOnlyDictionary ModuleDefinitions => _moduleDefinitions;
+ ///
+ /// Gets the for WinRT.Projection.dll.
+ ///
+ public ModuleDefinition? WinRTProjectionModuleDefinition => _winRTProjectionModuleDefinition;
+
+ ///
+ /// Gets the for WinRT.Component.dll.
+ ///
+ public ModuleDefinition? WinRTComponentModuleDefinition => _winRTComponentModuleDefinition;
+
///
/// Gets the type hierarchy entries.
///
@@ -221,6 +238,30 @@ public void TrackModuleDefinition(string path, ModuleDefinition module)
_ = _moduleDefinitions.TryAdd(path, module);
}
+ ///
+ /// Tracks the WinRT.Projection.dll loaded module definition.
+ ///
+ /// The loaded module.
+ [MemberNotNull(nameof(_winRTProjectionModuleDefinition))]
+ public void TrackWinRTProjectionModuleDefinition(ModuleDefinition module)
+ {
+ ThrowIfReadOnly();
+
+ _winRTProjectionModuleDefinition = module;
+ }
+
+ ///
+ /// Tracks the WinRT.Component.dll loaded module definition.
+ ///
+ /// The loaded module.
+ [MemberNotNull(nameof(_winRTComponentModuleDefinition))]
+ public void TrackWinRTComponentModuleDefinition(ModuleDefinition module)
+ {
+ ThrowIfReadOnly();
+
+ _winRTComponentModuleDefinition = module;
+ }
+
///
/// Tracks a pair of runtime class names for the type hierarchy.
///
diff --git a/src/WinRT.Interop.Generator/Helpers/GuidGenerator.cs b/src/WinRT.Interop.Generator/Helpers/GuidGenerator.cs
index eb723672e..851fcc888 100644
--- a/src/WinRT.Interop.Generator/Helpers/GuidGenerator.cs
+++ b/src/WinRT.Interop.Generator/Helpers/GuidGenerator.cs
@@ -6,7 +6,6 @@
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
-using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
using WindowsRuntime.InteropGenerator.References;
@@ -27,56 +26,22 @@ internal static class GuidGenerator
/// Generates the IID for the specified type by computing its Windows Runtime signature and deriving an IID from that signature.
///
/// The to generate the IID for.
+ /// The instance to use.
/// The instance to use.
/// Whether to use Windows.UI.Xaml projections.
/// The resulting IID for .
- public static Guid CreateIID(TypeSignature type, InteropReferences interopReferences, bool useWindowsUIXamlProjections)
+ public static Guid CreateIID(
+ TypeSignature type,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ bool useWindowsUIXamlProjections)
{
- string signature = SignatureGenerator.GetSignature(type, interopReferences, useWindowsUIXamlProjections);
+ string signature = SignatureGenerator.GetSignature(type, interopDefinitions, interopReferences, useWindowsUIXamlProjections);
Guid guid = CreateGuidFromSignature(signature);
return guid;
}
- ///
- /// Tries to resolve the IID for the specified type signature by checking well-known Windows Runtime
- /// interfaces and, if necessary, the type's .
- ///
- /// The type descriptor to try to get the IID for.
- /// Whether to use Windows.UI.Xaml projections.
- /// The instance to use.
- /// The resulting value, if found.
- /// Whether was succesfully retrieved.
- public static bool TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
- ITypeDescriptor type,
- bool useWindowsUIXamlProjections,
- InteropReferences interopReferences,
- out Guid iid)
- {
- // First try to get the IID from the custom-mapped types mapping
- if (WellKnownInterfaceIIDs.TryGetGUID(
- interfaceType: type,
- useWindowsUIXamlProjections: useWindowsUIXamlProjections,
- interopReferences: interopReferences,
- guid: out iid))
- {
- return true;
- }
-
- if (type.Resolve() is TypeDefinition typeDefinition)
- {
- // If the type was a normal projected type, then try to resolve the IID from the '[Guid]' attribute
- if (typeDefinition.TryGetGuidAttribute(interopReferences, out iid))
- {
- return true;
- }
- }
-
- iid = Guid.Empty;
-
- return false;
- }
-
///
/// Encodes a from a 16-byte sequence following RFC 4122 rules.
/// Adjusts byte order for little-endian systems and sets version and variant bits.
diff --git a/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.Projections.cs b/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.Projections.cs
index c875a115c..e5126573e 100644
--- a/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.Projections.cs
+++ b/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.Projections.cs
@@ -18,15 +18,21 @@ internal partial class SignatureGenerator
/// Tries to get the signature of a constructed generic type.
///
///
+ ///
///
///
/// The resulting signature, or in case of failures.
- private static string? GenericInstance(GenericInstanceTypeSignature typeSignature, InteropReferences interopReferences, bool useWindowsUIXamlProjections)
+ private static string? GenericInstance(
+ GenericInstanceTypeSignature typeSignature,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ bool useWindowsUIXamlProjections)
{
// If we fail to get the IID of the generic interface, we can't do anything else
- if (!GuidGenerator.TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
+ if (!TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
type: typeSignature.GenericType,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
iid: out Guid interfaceIid))
{
@@ -44,7 +50,7 @@ internal partial class SignatureGenerator
foreach (TypeSignature argumentSignature in typeSignature.TypeArguments)
{
handler.AppendFormatted(';');
- handler.AppendFormatted(GetSignature(argumentSignature, interopReferences, useWindowsUIXamlProjections));
+ handler.AppendFormatted(GetSignature(argumentSignature, interopDefinitions, interopReferences, useWindowsUIXamlProjections));
}
handler.AppendFormatted(')');
@@ -77,12 +83,14 @@ internal partial class SignatureGenerator
///
/// The full name of the value type.
/// The to generate the signature for.
+ ///
///
///
/// The resulting signature, or in case of failures.
private static string? ValueType(
string typeFullName,
TypeDefinition typeDefinition,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
bool useWindowsUIXamlProjections)
{
@@ -114,7 +122,7 @@ internal partial class SignatureGenerator
}
handler.AppendFormatted(';');
- handler.AppendFormatted(GetSignature(fieldSignature, interopReferences, useWindowsUIXamlProjections));
+ handler.AppendFormatted(GetSignature(fieldSignature, interopDefinitions, interopReferences, useWindowsUIXamlProjections));
}
handler.AppendFormatted(')');
@@ -126,14 +134,20 @@ internal partial class SignatureGenerator
/// Tries to get the signature of a delegate type.
///
/// The to generate the signature for.
+ ///
///
///
- private static string? Delegate(TypeDefinition typeDefinition, InteropReferences interopReferences, bool useWindowsUIXamlProjections)
+ private static string? Delegate(
+ TypeDefinition typeDefinition,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ bool useWindowsUIXamlProjections)
{
// Just like for generic instantiations, we need to resolve the IID for the type first
- if (!GuidGenerator.TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
+ if (TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
type: typeDefinition,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
iid: out Guid iid))
{
@@ -149,25 +163,28 @@ internal partial class SignatureGenerator
///
/// The full name of the class type.
/// The to generate the signature for.
+ ///
///
///
/// The resulting signature, or in case of failures.
private static string? Class(
string typeFullName,
TypeDefinition typeDefinition,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
bool useWindowsUIXamlProjections)
{
// If we can resolve the default interface type from the projected runtime class, use it
- if (TryGetDefaultInterfaceFromAttribute(typeDefinition, interopReferences, out TypeSignature? defaultInterface))
+ if (TryGetDefaultInterfaceFromAttribute(typeDefinition, interopDefinitions, interopReferences, out TypeSignature? defaultInterface))
{
- return $"rc({typeFullName};{GetSignature(defaultInterface, interopReferences, useWindowsUIXamlProjections)})";
+ return $"rc({typeFullName};{GetSignature(defaultInterface, interopDefinitions, interopReferences, useWindowsUIXamlProjections)})";
}
// Otherwise, get the IID from the type definition and use it
- if (!GuidGenerator.TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
+ if (!TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
type: typeDefinition,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
iid: out Guid iid))
{
@@ -181,14 +198,20 @@ internal partial class SignatureGenerator
/// Tries to get the signature of an interface type.
///
/// The to generate the signature for.
+ ///
///
///
- private static string? Interface(TypeDefinition typeDefinition, InteropReferences interopReferences, bool useWindowsUIXamlProjections)
+ private static string? Interface(
+ TypeDefinition typeDefinition,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ bool useWindowsUIXamlProjections)
{
// For all interface types, we should always be able to resolve their IID
- if (!GuidGenerator.TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
+ if (!TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
type: typeDefinition,
useWindowsUIXamlProjections: useWindowsUIXamlProjections,
+ interopDefinitions: interopDefinitions,
interopReferences: interopReferences,
iid: out Guid iid))
{
@@ -203,12 +226,14 @@ internal partial class SignatureGenerator
///
///
/// The to generate the signature for.
+ ///
///
///
/// The resulting signature, or in case of failures.
private static string? Box(
BoxedTypeSignature typeSignature,
TypeDefinition typeDefinition,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
bool useWindowsUIXamlProjections)
{
@@ -227,17 +252,22 @@ internal partial class SignatureGenerator
guid: out Guid iid);
// Construct the signature for the boxed delegate (the base type will be the possibly constructed delegate)
- return $"pinterface({{{iid}}};{GetSignature(typeSignature.BaseType, interopReferences, useWindowsUIXamlProjections)})";
+ return $"pinterface({{{iid}}};{GetSignature(typeSignature.BaseType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)})";
}
///
/// Tries to get the signature of an array type.
///
///
+ ///
///
///
- private static string? Array(SzArrayTypeSignature typeSignature, InteropReferences interopReferences, bool useWindowsUIXamlProjections)
+ private static string? Array(
+ SzArrayTypeSignature typeSignature,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ bool useWindowsUIXamlProjections)
{
- return $"pinterface({{61c17707-2d65-11e0-9ae8-d48564015472}};{GetSignature(typeSignature.BaseType, interopReferences, useWindowsUIXamlProjections)})";
+ return $"pinterface({{61c17707-2d65-11e0-9ae8-d48564015472}};{GetSignature(typeSignature.BaseType, interopDefinitions, interopReferences, useWindowsUIXamlProjections)})";
}
}
diff --git a/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs b/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs
index 14f70564b..b6b66bc1c 100644
--- a/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs
+++ b/src/WinRT.Interop.Generator/Helpers/SignatureGenerator.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using System;
using System.Diagnostics.CodeAnalysis;
using AsmResolver.DotNet;
using AsmResolver.DotNet.Signatures;
@@ -21,11 +22,13 @@ internal static partial class SignatureGenerator
/// Generates the Windows Runtime signature for the specified type.
///
/// The to generate the signature for.
+ /// The instance to use.
/// The instance to use.
/// Whether to use Windows.UI.Xaml projections.
/// The resulting signature for .
public static string GetSignature(
TypeSignature type,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
bool useWindowsUIXamlProjections)
{
@@ -66,15 +69,15 @@ public static string GetSignature(
ElementType.Object => ObjectSignature,
ElementType.String => StringSignature,
ElementType.Type => TypeSignature,
- ElementType.GenericInst => GenericInstance((GenericInstanceTypeSignature)type, interopReferences, useWindowsUIXamlProjections),
+ ElementType.GenericInst => GenericInstance((GenericInstanceTypeSignature)type, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
ElementType.ValueType when typeDefinition.IsClass && typeDefinition.IsEnum => Enum(typeFullName, typeDefinition, interopReferences),
ElementType.ValueType when typeDefinition.IsClass && type.IsTypeOfGuid(interopReferences) => GuidSignature,
- ElementType.ValueType when typeDefinition.IsClass => ValueType(typeFullName, typeDefinition, interopReferences, useWindowsUIXamlProjections),
- ElementType.Class when typeDefinition.IsClass && typeDefinition.IsDelegate => Delegate(typeDefinition, interopReferences, useWindowsUIXamlProjections),
- ElementType.Class when typeDefinition.IsClass => Class(typeFullName, typeDefinition, interopReferences, useWindowsUIXamlProjections),
- ElementType.Class when typeDefinition.IsInterface => Interface(typeDefinition, interopReferences, useWindowsUIXamlProjections),
- ElementType.Boxed => Box((BoxedTypeSignature)type, typeDefinition, interopReferences, useWindowsUIXamlProjections),
- ElementType.SzArray => Array((SzArrayTypeSignature)type, interopReferences, useWindowsUIXamlProjections),
+ ElementType.ValueType when typeDefinition.IsClass => ValueType(typeFullName, typeDefinition, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
+ ElementType.Class when typeDefinition.IsClass && typeDefinition.IsDelegate => Delegate(typeDefinition, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
+ ElementType.Class when typeDefinition.IsClass => Class(typeFullName, typeDefinition, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
+ ElementType.Class when typeDefinition.IsInterface => Interface(typeDefinition, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
+ ElementType.Boxed => Box((BoxedTypeSignature)type, typeDefinition, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
+ ElementType.SzArray => Array((SzArrayTypeSignature)type, interopDefinitions, interopReferences, useWindowsUIXamlProjections),
_ => null
};
@@ -92,20 +95,107 @@ public static string GetSignature(
throw WellKnownInteropExceptions.TypeSignatureGenerationError(type);
}
+ ///
+ /// Tries to resolve the IID for the specified type signature by checking well-known Windows Runtime
+ /// interfaces and, if necessary, the type's .
+ ///
+ /// The type descriptor to try to get the IID for.
+ /// Whether to use Windows.UI.Xaml projections.
+ /// The instance to use.
+ /// The instance to use.
+ /// The resulting value, if found.
+ /// Whether was successfully retrieved.
+ private static bool TryGetIIDFromWellKnownInterfaceIIDsOrAttribute(
+ ITypeDescriptor type,
+ bool useWindowsUIXamlProjections,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ out Guid iid)
+ {
+ // First try to get the IID from the custom-mapped types mapping
+ if (WellKnownInterfaceIIDs.TryGetGUID(
+ interfaceType: type,
+ useWindowsUIXamlProjections: useWindowsUIXamlProjections,
+ interopReferences: interopReferences,
+ guid: out iid))
+ {
+ return true;
+ }
+
+ // If we can resolve the type, try to retrieve the IID from the '[Guid]' attribute on it
+ if (type.Resolve() is TypeDefinition typeDefinition)
+ {
+ return TryGetIIDFromAttribute(
+ typeDefinition,
+ interopDefinitions,
+ interopReferences,
+ out iid);
+ }
+
+ iid = Guid.Empty;
+
+ return false;
+ }
+
+ ///
+ /// Attempts to retrieve the IID for the specified type by checking the
+ /// attribute applied to it, if presen. The type is assumed to be some projected Windows Runtime interface or delegate type.
+ ///
+ /// The type descriptor to try to get the IID for.
+ /// The instance to use.
+ /// The instance to use.
+ /// The resulting value, if found.
+ /// Whether was successfully retrieved.
+ private static bool TryGetIIDFromAttribute(
+ TypeDefinition type,
+ InteropDefinitions interopDefinitions,
+ InteropReferences interopReferences,
+ out Guid iid)
+ {
+ // If the type had the '[Guid]' attribute directly on it, get it from there (this is the case for interfaces)
+ if (type.TryGetGuidAttribute(interopReferences, out iid))
+ {
+ return true;
+ }
+
+ // For delegates, try to get the projected type from the 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))
+ {
+ return projectedType.TryGetGuidAttribute(interopReferences, out iid);
+ }
+
+ iid = Guid.Empty;
+
+ return false;
+ }
+
///
/// Attempts to retrieve the default interface signature from the [WindowsRuntimeDefaultInterface]
/// attribute applied to the specified type, which is assumed to be some projected Windows Runtime class.
///
/// The type definition to inspect for the default interface attribute.
+ /// The instance to use.
/// The instance to use.
/// The instance for the default interface for , if found.
/// Whether was successfully retrieved.
private static bool TryGetDefaultInterfaceFromAttribute(
TypeDefinition type,
+ InteropDefinitions interopDefinitions,
InteropReferences interopReferences,
[NotNullWhen(true)] out TypeSignature? defaultInterface)
{
- if (type.TryGetCustomAttribute(interopReferences.WindowsRuntimeDefaultInterfaceAttribute, out CustomAttribute? customAttribute))
+ // 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))
+ {
+ defaultInterface = null;
+
+ return false;
+ }
+
+ // Try to lookup '[WindowsRuntimeDefaultInterface]' from the projected type, if we found it
+ if (projectedType.TryGetCustomAttribute(interopReferences.WindowsRuntimeDefaultInterfaceAttribute, out CustomAttribute? customAttribute))
{
if (customAttribute.Signature is { FixedArguments: [{ Element: TypeSignature signature }, ..] })
{
diff --git a/src/WinRT.Interop.Generator/References/InteropDefinitions.cs b/src/WinRT.Interop.Generator/References/InteropDefinitions.cs
index 4fd303183..613f88b83 100644
--- a/src/WinRT.Interop.Generator/References/InteropDefinitions.cs
+++ b/src/WinRT.Interop.Generator/References/InteropDefinitions.cs
@@ -32,13 +32,31 @@ internal sealed class InteropDefinitions
/// Creates a new instance.
///
/// The instance to use.
- public InteropDefinitions(InteropReferences interopReferences)
+ /// 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? windowsRuntimeComponentModule)
{
_interopReferences = interopReferences;
_userDefinedInterfaceEntries = [];
_szArrayInterfaceEntries = [];
+
+ WindowsRuntimeProjectionModule = windowsRuntimeProjectionModule;
+ WindowsRuntimeComponentModule = windowsRuntimeComponentModule;
}
+ ///
+ /// Gets the for the Windows Runtime projection assembly (i.e. WinRT.Projection.dll).
+ ///
+ public ModuleDefinition WindowsRuntimeProjectionModule { get; }
+
+ ///
+ /// Gets the for the Windows Runtime component assembly (i.e. WinRT.Component.dll).
+ ///
+ public ModuleDefinition? WindowsRuntimeComponentModule { get; }
+
///
/// Gets the for the IgnoresAccessChecksToAttribute type.
///
diff --git a/src/WinRT.Interop.Generator/References/InteropNames.cs b/src/WinRT.Interop.Generator/References/InteropNames.cs
index 3baba1809..eff666568 100644
--- a/src/WinRT.Interop.Generator/References/InteropNames.cs
+++ b/src/WinRT.Interop.Generator/References/InteropNames.cs
@@ -11,29 +11,39 @@ namespace WindowsRuntime.InteropGenerator.References;
internal static class InteropNames
{
///
- /// The name of the generated interop .dll.
+ /// The name of the generated interop .dll (i.e. WinRT.Interop.dll).
///
- public const string InteropDllName = "WinRT.Interop.dll";
+ public const string WindowsRuntimeInteropDllName = "WinRT.Interop.dll";
///
- /// The name of the generated interop assembly.
+ /// The name of the generated projection .dll (i.e. WinRT.Projection.dll).
///
- public static ReadOnlySpan InteropAssemblyNameUtf8 => "WinRT.Interop"u8;
+ public const string WindowsRuntimeProjectionDllName = "WinRT.Projection.dll";
///
- /// The name of the generated interop .dll.
+ /// The name of the generated component .dll (i.e. WinRT.Component.dll).
///
- public static ReadOnlySpan InteropDllNameUtf8 => "WinRT.Interop.dll"u8;
+ public const string WindowsRuntimeComponentDllName = "WinRT.Component.dll";
///
- /// The name of the WinRT runtime .dll.
+ /// The name of the generated interop assembly (i.e. WinRT.Interop.dll).
///
- public static ReadOnlySpan WinRTRuntimeDllNameUtf8 => "WinRT.Runtime.dll"u8;
+ public static ReadOnlySpan WindowsRuntimeInteropAssemblyNameUtf8 => "WinRT.Interop"u8;
///
- /// The current name of the WinRT runtime .dll.
+ /// The name of the generated interop .dll (i.e. WinRT.Interop.dll).
///
- public static ReadOnlySpan WinRTRuntime2DllNameUtf8 => "WinRT.Runtime2.dll"u8;
+ public static ReadOnlySpan WindowsRuntimeInteropDllNameUtf8 => "WinRT.Interop.dll"u8;
+
+ ///
+ /// The name of the Windows Runtime .dll (i.e. WinRT.Runtime.dll).
+ ///
+ public static ReadOnlySpan WindowsRuntimeDllNameUtf8 => "WinRT.Runtime.dll"u8;
+
+ ///
+ /// The current name of the Windows Runtime .dll (i.e. WinRT.Runtime2.dll).
+ ///
+ public static ReadOnlySpan WindowsRuntime2DllNameUtf8 => "WinRT.Runtime2.dll"u8;
///
/// The name of the Windows SDK projections .dll.
diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs
index 17c82b425..c2ccd6f84 100644
--- a/src/WinRT.Interop.Generator/References/InteropReferences.cs
+++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs
@@ -21,7 +21,7 @@ internal sealed class InteropReferences
private readonly CorLibTypeFactory _corLibTypeFactory;
///
- /// The for the Windows Runtime assembly.
+ /// The for the Windows Runtime assembly (i.e. WinRT.Runtime.dll).
///
private readonly IResolutionScope _windowsRuntimeModule;
@@ -34,7 +34,7 @@ internal sealed class InteropReferences
/// Creates a new instance.
///
/// The currently in use.
- /// The for the Windows Runtime assembly.
+ /// The for the Windows Runtime assembly (i.e. WinRT.Runtime.dll).
/// The for the Windows SDK projection assembly.
public InteropReferences(
CorLibTypeFactory corLibTypeFactory,
@@ -103,7 +103,7 @@ public InteropReferences(
public CorLibTypeSignature Object => _corLibTypeFactory.Object;
///
- /// Gets the for the Windows Runtime assembly.
+ /// Gets the for the Windows Runtime assembly (i.e. WinRT.Runtime.dll).
///
public IResolutionScope WindowsRuntimeModule => _windowsRuntimeModule;
diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h
index 25461026e..92f218ed8 100644
--- a/src/cswinrt/code_writers.h
+++ b/src/cswinrt/code_writers.h
@@ -4816,6 +4816,11 @@ R"(
void write_winrt_reference_type_attribute(writer& w, TypeDef const& type)
{
+ if (settings.reference_projection)
+ {
+ return;
+ }
+
w.write("[WindowsRuntimeReferenceType(typeof(%?))]\n", type.TypeName());
}
@@ -4860,6 +4865,11 @@ R"(
void write_default_interface_attribute(writer& w, TypeDef const& type)
{
+ if (settings.reference_projection)
+ {
+ return;
+ }
+
auto default_interface = get_default_interface(type);
for_typedef(w, get_type_semantics(default_interface), [&](auto type)
@@ -9147,19 +9157,11 @@ return new %(valueReference);
{
method_signature signature{ get_delegate_invoke(type) };
w.write(R"(
-%%%%% delegate % %(%);
+%%%% delegate % %(%);
)",
bind(type),
bind(type, false),
bind(type),
- bind([&](writer& w)
- {
- if (settings.reference_projection)
- {
- write_guid_attribute(w, type);
- w.write("\n");
- }
- }),
internal_accessibility(),
bind(signature),
bind(type, typedef_name_type::Projected, false),