diff --git a/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs b/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs index aba7fa179..7d45685d5 100644 --- a/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs +++ b/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs @@ -104,6 +104,8 @@ public static void EmitPrivateProjectionsTypeMapAssemblyTargetAttributes(SourceP { _ = builder.AppendLine($""" [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("{assemblyName}")] + [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("{assemblyName}")] + [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("{assemblyName}")] """); } @@ -129,6 +131,14 @@ public static void EmitDefaultTypeMapAssemblyTargetAttributes(SourceProductionCo [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Interop")] //[assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Projection")] [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Runtime2")] + + [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Interop")] + //[assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Projection")] + [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Runtime2")] + + [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Interop")] + //[assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Projection")] + [assembly: global::System.Runtime.InteropServices.TypeMapAssemblyTarget("WinRT.Runtime2")] """; context.AddSource("TypeMapAssemblyTarget.g.cs", source); diff --git a/src/Tests/FunctionalTests/TypeMarshaling/Program.cs b/src/Tests/FunctionalTests/TypeMarshaling/Program.cs new file mode 100644 index 000000000..266b849b0 --- /dev/null +++ b/src/Tests/FunctionalTests/TypeMarshaling/Program.cs @@ -0,0 +1,53 @@ +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using TestComponent; +using TestComponentCSharp; + +bool success = true; + +SetTypeProperties setTypeProperties = new(); + +// TODO: This test case fails because of a System.InvalidCastException when passing in CustomTestType to GetPropertyInfoWithIType. +// Reenable this once the issue is resolved. +// +//// Trimmed Metadata test case +//// Do not reference TestComponentCSharp::TestType1 in managed because it needs to be trimmed to test the Metadata TypeKind scenario +//String expectedMetadataPropertyInfo = "TestComponentCSharp.TestType1 Metadata"; +//CustomTestType customTestType = new(); +//if (setTypeProperties.GetPropertyInfoWithIType(customTestType) != expectedMetadataPropertyInfo) +//{ +// success = false; +//} + +// Custom TypeKind test case +String expectedCustomTypePropertyInfo = "CustomTestType, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Custom"; +SetTypeProperties customSetTypeProperties = new(); +if (setTypeProperties.GetPropertyInfoFromCustomType(typeof(CustomTestType)) != expectedCustomTypePropertyInfo) +{ + success = false; +} + +// Primitive TypeKind test case +String expectedPrimitiveTypePropertyInfo = "Int32 Primitive"; +SetTypeProperties primitiveSetTypeProperties = new(); +if (setTypeProperties.GetPropertyInfoFromCustomType(typeof(int)) != expectedPrimitiveTypePropertyInfo) +{ + success = false; +} + +// Primitive TypeKind test case 2 +String expectedPrimitiveTypePropertyInfo2 = "Int64 Primitive"; +SetTypeProperties primitiveSetTypeProperties2 = new(); +if (setTypeProperties.GetPropertyInfoFromCustomType(typeof(System.Int64)) != expectedPrimitiveTypePropertyInfo2) +{ + success = false; +} + +return success ? 100 : 101; + +sealed class CustomTestType : IType +{ + public System.Type TypeProperty { get; set; } +} + diff --git a/src/Tests/FunctionalTests/TypeMarshaling/Properties/launchSettings.json b/src/Tests/FunctionalTests/TypeMarshaling/Properties/launchSettings.json new file mode 100644 index 000000000..1bc4d802e --- /dev/null +++ b/src/Tests/FunctionalTests/TypeMarshaling/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "TypeMarshaling": { + "commandName": "Project", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/src/Tests/FunctionalTests/TypeMarshaling/TypeMarshaling.csproj b/src/Tests/FunctionalTests/TypeMarshaling/TypeMarshaling.csproj new file mode 100644 index 000000000..a54d35df2 --- /dev/null +++ b/src/Tests/FunctionalTests/TypeMarshaling/TypeMarshaling.csproj @@ -0,0 +1,16 @@ + + + Exe + $(FunctionalTestsBuildTFMs) + x86;x64 + win-x86;win-x64 + $(MSBuildProjectDirectory)\..\PublishProfiles\win-$(Platform).pubxml + + + + + + + + + diff --git a/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.cpp b/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.cpp index ae5bad157..c0bd56d43 100644 --- a/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.cpp +++ b/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.cpp @@ -5,9 +5,39 @@ #include "CustomBindableVectorTest.g.cpp" #include "CustomBindableObservableVectorTest.g.cpp" #include "CustomIteratorTest.g.cpp" +#include "SetTypeProperties.g.cpp" +#include namespace winrt::TestComponentCSharp::implementation { + SetTypeProperties::SetTypeProperties() + { + + } + + winrt::hstring SetTypeProperties::GetPropertyInfoWithIType(IType testObject) + { + testObject.TypeProperty(winrt::xaml_typename()); + winrt::hstring kind; + switch (testObject.TypeProperty().Kind) + { + case Windows::UI::Xaml::Interop::TypeKind::Custom: + kind = winrt::hstring(L"Custom"); + case Windows::UI::Xaml::Interop::TypeKind::Metadata: + kind = winrt::hstring(L"Metadata"); + default: + kind = winrt::hstring(L"Primitive"); + } + return testObject.TypeProperty().Name + L" " + kind; + } + + winrt::hstring SetTypeProperties::GetPropertyInfoFromCustomType(winrt::Windows::UI::Xaml::Interop::TypeName typeName) + { + TestComponentCSharp::Class TestObject; + TestObject.TypeProperty(typeName); + return TestObject.GetTypePropertyAbiName() + L" " + TestObject.GetTypePropertyKind(); + } + CustomBindableIteratorTest::CustomBindableIteratorTest() { diff --git a/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.h b/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.h index ab37f5a75..48aefeace 100644 --- a/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.h +++ b/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.h @@ -4,9 +4,18 @@ #include "CustomBindableVectorTest.g.h" #include "CustomBindableObservableVectorTest.g.h" #include "CustomIteratorTest.g.h" +#include "SetTypeProperties.g.h" +#include namespace winrt::TestComponentCSharp::implementation { + struct SetTypeProperties : SetTypePropertiesT + { + SetTypeProperties(); + winrt::hstring GetPropertyInfoWithIType(IType testObject); + winrt::hstring GetPropertyInfoFromCustomType(winrt::Windows::UI::Xaml::Interop::TypeName typeName); + }; + struct CustomBindableIteratorTest : CustomBindableIteratorTestT { CustomBindableIteratorTest(); @@ -72,6 +81,11 @@ namespace winrt::TestComponentCSharp::implementation namespace winrt::TestComponentCSharp::factory_implementation { + struct SetTypeProperties : SetTypePropertiesT + { + + }; + struct CustomBindableIteratorTest : CustomBindableIteratorTestT { diff --git a/src/Tests/TestComponentCSharp/TestComponentCSharp.idl b/src/Tests/TestComponentCSharp/TestComponentCSharp.idl index 7a10f8674..77b008141 100644 --- a/src/Tests/TestComponentCSharp/TestComponentCSharp.idl +++ b/src/Tests/TestComponentCSharp/TestComponentCSharp.idl @@ -106,6 +106,11 @@ namespace TestComponentCSharp Int32 DrawTo(); } + interface IType + { + Windows.UI.Xaml.Interop.TypeName TypeProperty{ get; set; }; + }; + interface IProperties1 { Int32 ReadWriteProperty{ get; }; @@ -152,6 +157,20 @@ namespace TestComponentCSharp static ISingleton Instance; } + [default_interface] + runtimeclass SetTypeProperties + { + SetTypeProperties(); + String GetPropertyInfoWithIType(IType testObject); + String GetPropertyInfoFromCustomType(Windows.UI.Xaml.Interop.TypeName typeName); + } + + // Do not reference TestComponentCSharp::TestType1 in managed because it needs to be trimmed to test the Metadata TypeKind scenario in the TypeHandling project + runtimeclass TestType1 + { + void f(); + } + [default_interface, gc_pressure(Windows.Foundation.Metadata.GCPressureAmount.High)] runtimeclass Class : Windows.Foundation.IStringable diff --git a/src/Tests/UnitTest/OOPObject.cs b/src/Tests/UnitTest/OOPObject.cs deleted file mode 100644 index 6993e5ba3..000000000 --- a/src/Tests/UnitTest/OOPObject.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using Windows.Foundation; -using Windows.Win32; -using Windows.Win32.System.Com; -using WindowsRuntime.InteropServices; - -namespace UnitTest -{ - // https://docs.microsoft.com/windows/win32/api/unknwn/nn-unknwn-iclassfactory - [ComImport] - [ComVisible(false)] - [Guid("00000001-0000-0000-C000-000000000046")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - interface IClassFactory - { - void CreateInstance( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, - ref Guid riid, - out IntPtr ppvObject); - - void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); - } - - [ComVisible(true)] - internal class WinRTClassFactory : IClassFactory - { - private static readonly Guid IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); - - - public static void RegisterClass(IClassFactory classFactory) - { - RegisterClassObject(typeof(T).GUID, classFactory); - } - - private static void RegisterClassObject(Guid clsid, object factory) - { - int hr = PInvoke.CoRegisterClassObject(in clsid, factory, CLSCTX.CLSCTX_LOCAL_SERVER, (int)REGCLS.REGCLS_MULTIPLEUSE, out uint _); - if (hr < 0) - { - Marshal.ThrowExceptionForHR(hr); - } - } - - private readonly Func createFunction; - private readonly Dictionary> marshalFuncByGuid; - - public WinRTClassFactory(Func createFunction, Dictionary> marshalFuncByGuid) - { - this.createFunction = createFunction ?? throw new ArgumentNullException(nameof(createFunction)); - this.marshalFuncByGuid = marshalFuncByGuid ?? throw new ArgumentNullException(nameof(marshalFuncByGuid)); - } - - public void CreateInstance( - [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, - ref Guid riid, - out IntPtr ppvObject) - { - if (pUnkOuter != null) - { - throw new COMException(); - } - - object obj = this.createFunction(); - if (riid == IUnknown) - { - unsafe - { - ppvObject = (IntPtr)WindowsRuntimeMarshal.ConvertToUnmanaged(obj); - } - } - else - { - if (!this.marshalFuncByGuid.TryGetValue(riid, out Func marshalFunc)) - { - throw new InvalidCastException(); - } - - ppvObject = marshalFunc(obj); - } - } - - public void LockServer(bool fLock) - { - // No-op - } - } - - [ComVisible(true)] - [Guid("15F1005B-E23A-4154-9417-CCD083D452BB")] - [ComDefaultInterface(typeof(IAsyncAction))] - internal class OOPAsyncAction : IAsyncAction - { - public bool delegateCalled; - - public AsyncActionCompletedHandler Completed { get; set; } - - public Exception ErrorCode => throw new NotImplementedException(); - - public uint Id => throw new NotImplementedException(); - - public AsyncStatus Status => throw new NotImplementedException(); - - public void Cancel() - { - } - - public void Close() - { - Completed(this, AsyncStatus.Completed); - } - - public void GetResults() - { - delegateCalled = true; - } - } -} \ No newline at end of file diff --git a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs index 064d093ab..fdcda0651 100644 --- a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs +++ b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs @@ -35,6 +35,7 @@ using WindowsRuntime.InteropServices; using WindowsRuntime; using System.Runtime.InteropServices.Marshalling; +using Windows.Foundation.Tasks; // Test SupportedOSPlatform warnings for APIs targeting 10.0.19041.0: [assembly: global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.18362.0")] @@ -546,12 +547,36 @@ public void TestBufferTryGetArraySubset() Assert.Equal(2, array.Count); } - [Fact] - public void TestTypePropertyWithSystemType() - { - TestObject.TypeProperty = typeof(System.Type); - Assert.Equal("Windows.UI.Xaml.Interop.TypeName", TestObject.GetTypePropertyAbiName()); - Assert.Equal("Metadata", TestObject.GetTypePropertyKind()); + [Theory] + [InlineData(typeof(TestComponent.Nested), "TestComponent.Nested", "Metadata")] + [InlineData(typeof(TestComponent.Param6Handler), "TestComponent.Param6Handler", "Metadata")] + [InlineData(typeof(TestComponent.Param7Handler), "TestComponent.Param7Handler", "Metadata")] + [InlineData(typeof(TestComponent.Class), "TestComponent.Class", "Metadata")] + [InlineData(typeof(TestComponentCSharp.EnumValue), "TestComponentCSharp.EnumValue", "Metadata")] + [InlineData(typeof(Type), "Windows.UI.Xaml.Interop.TypeName", "Metadata")] + [InlineData(typeof(Guid), "Guid", "Metadata")] + [InlineData(typeof(Object), "Object", "Metadata")] + [InlineData(typeof(String), "String", "Metadata")] + [InlineData(typeof(TimeSpan), "Windows.Foundation.TimeSpan", "Metadata")] + [InlineData(typeof(long), "Int64", "Primitive")] + [InlineData(typeof(int), "Int32", "Primitive")] + [InlineData(typeof(short), "Int16", "Primitive")] + [InlineData(typeof(ulong), "UInt64", "Primitive")] + [InlineData(typeof(uint), "UInt32", "Primitive")] + [InlineData(typeof(ushort), "UInt16", "Primitive")] + [InlineData(typeof(byte), "UInt8", "Primitive")] + [InlineData(typeof(char), "Char16", "Primitive")] + [InlineData(typeof(float), "Single", "Primitive")] + [InlineData(typeof(double), "Double", "Primitive")] + [InlineData(typeof(bool), "Boolean", "Primitive")] + [InlineData(typeof(IServiceProvider), "Microsoft.UI.Xaml.IXamlServiceProvider", "Metadata")] + [InlineData(typeof(IDisposable), "Windows.Foundation.IClosable", "Metadata")] + public void TestTypePropertyConvertToUnmanaged(Type type, string name, string kind) + { + // test method here + TestObject.TypeProperty = type; + Assert.Equal(name, TestObject.GetTypePropertyAbiName()); + Assert.Equal(kind, TestObject.GetTypePropertyKind()); } class CustomDictionary : Dictionary { } @@ -2012,18 +2037,18 @@ public void TestAsyncActionWait() { var asyncAction = TestObject.DoitAsync(); TestObject.CompleteAsync(); - asyncAction.Wait(); + asyncAction.AsTask().Wait(); Assert.Equal(AsyncStatus.Completed, asyncAction.Status); asyncAction = TestObject.DoitAsync(); TestObject.CompleteAsync(E_FAIL); - var e = Assert.Throws(() => asyncAction.Wait()); + var e = Assert.Throws(() => asyncAction.AsTask().Wait()); Assert.Equal(E_FAIL, e.InnerException.HResult); Assert.Equal(AsyncStatus.Error, asyncAction.Status); asyncAction = TestObject.DoitAsync(); asyncAction.Cancel(); - e = Assert.Throws(() => asyncAction.Wait()); + e = Assert.Throws(() => asyncAction.AsTask().Wait()); Assert.True(e.InnerException is TaskCanceledException); Assert.Equal(AsyncStatus.Canceled, asyncAction.Status); } @@ -2100,18 +2125,18 @@ public void TestAsyncActionWithProgressWait() { var asyncAction = TestObject.DoitAsyncWithProgress(); TestObject.CompleteAsync(); - asyncAction.Wait(); + asyncAction.AsTask().Wait(); Assert.Equal(AsyncStatus.Completed, asyncAction.Status); asyncAction = TestObject.DoitAsyncWithProgress(); TestObject.CompleteAsync(E_FAIL); - var e = Assert.Throws(() => asyncAction.Wait()); + var e = Assert.Throws(() => asyncAction.AsTask().Wait()); Assert.Equal(E_FAIL, e.InnerException.HResult); Assert.Equal(AsyncStatus.Error, asyncAction.Status); asyncAction = TestObject.DoitAsyncWithProgress(); asyncAction.Cancel(); - e = Assert.Throws(() => asyncAction.Wait()); + e = Assert.Throws(() => asyncAction.AsTask().Wait()); Assert.True(e.InnerException is TaskCanceledException); Assert.Equal(AsyncStatus.Canceled, asyncAction.Status); } @@ -2152,18 +2177,18 @@ public void TestAsyncOperationWait() { var asyncOperation = TestObject.AddAsync(42, 8); TestObject.CompleteAsync(); - asyncOperation.Wait(); + asyncOperation.AsTask().Wait(); Assert.Equal(AsyncStatus.Completed, asyncOperation.Status); asyncOperation = TestObject.AddAsync(42, 8); TestObject.CompleteAsync(E_FAIL); - var e = Assert.Throws(() => asyncOperation.Wait()); + var e = Assert.Throws(() => asyncOperation.AsTask().Wait()); Assert.Equal(E_FAIL, e.InnerException.HResult); Assert.Equal(AsyncStatus.Error, asyncOperation.Status); asyncOperation = TestObject.AddAsync(42, 8); asyncOperation.Cancel(); - e = Assert.Throws(() => asyncOperation.Wait()); + e = Assert.Throws(() => asyncOperation.AsTask().Wait()); Assert.True(e.InnerException is TaskCanceledException); Assert.Equal(AsyncStatus.Canceled, asyncOperation.Status); } @@ -2243,18 +2268,18 @@ public void TestAsyncOperationWithProgressWait() { var asyncOperation = TestObject.AddAsyncWithProgress(42, 8); TestObject.CompleteAsync(); - asyncOperation.Wait(); + asyncOperation.AsTask().Wait(); Assert.Equal(AsyncStatus.Completed, asyncOperation.Status); asyncOperation = TestObject.AddAsyncWithProgress(42, 8); TestObject.CompleteAsync(E_FAIL); - var e = Assert.Throws(() => asyncOperation.Wait()); + var e = Assert.Throws(() => asyncOperation.AsTask().Wait()); Assert.Equal(E_FAIL, e.InnerException.HResult); Assert.Equal(AsyncStatus.Error, asyncOperation.Status); asyncOperation = TestObject.AddAsyncWithProgress(42, 8); asyncOperation.Cancel(); - e = Assert.Throws(() => asyncOperation.Wait()); + e = Assert.Throws(() => asyncOperation.AsTask().Wait()); Assert.True(e.InnerException is TaskCanceledException); Assert.Equal(AsyncStatus.Canceled, asyncOperation.Status); } @@ -3427,34 +3452,34 @@ public void TestEventRemovalByEventSource() Assert.True(eventCalled2); } - [Fact] - public unsafe void TestProxiedDelegate() - { - var obj = new OOPAsyncAction(); - var factory = new WinRTClassFactory( - () => obj, - new Dictionary>() - { - { typeof(IAsyncAction).GUID, obj => (IntPtr)WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged((IAsyncAction) obj, typeof(IAsyncAction).GUID).GetThisPtr() }, - }); - - WinRTClassFactory.RegisterClass(factory); - - var currentExecutingDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var launchExePath = $"{currentExecutingDir}\\OOPExe.exe"; - var proc = Process.Start(launchExePath); - Thread.Sleep(5000); - obj.Close(); - Assert.True(obj.delegateCalled); - - try - { - proc.Kill(); - } - catch (Exception) - { - } - } + //[Fact] + //public unsafe void TestProxiedDelegate() + //{ + // var obj = new OOPAsyncAction(); + // var factory = new WinRTClassFactory( + // () => obj, + // new Dictionary>() + // { + // { typeof(IAsyncAction).GUID, obj => (IntPtr)WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged((IAsyncAction) obj, typeof(IAsyncAction).GUID).GetThisPtr() }, + // }); + + // WinRTClassFactory.RegisterClass(factory); + + // var currentExecutingDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + // var launchExePath = $"{currentExecutingDir}\\OOPExe.exe"; + // var proc = Process.Start(launchExePath); + // Thread.Sleep(5000); + // obj.Close(); + // Assert.True(obj.delegateCalled); + + // try + // { + // proc.Kill(); + // } + // catch (Exception) + // { + // } + //} [Fact] private async Task TestPnpPropertiesInLoop() diff --git a/src/Tests/UnitTest/TestModuleInitializer.cs b/src/Tests/UnitTest/TestModuleInitializer.cs new file mode 100644 index 000000000..859978fde --- /dev/null +++ b/src/Tests/UnitTest/TestModuleInitializer.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Reflection; + +namespace UnitTest; + +// CsWinRT makes use of the .NET typemap to register all the projected types. +// As part this, .NET makes use of TypeMapAssemblyTarget to discover the assemblies with the type map. +// But this needs to be on the launching executable for it to discover them by default. Given with +// a test runner, they aren't, this does the alternative way of setting the assembly with that attribute +// as the entry assembly which then allows .NET to discover it. +internal static class ProjectionTypesInitializer +{ + [System.Runtime.CompilerServices.ModuleInitializer] + internal static void InitializeProjectionTypes() + { + Assembly.SetEntryAssembly(typeof(ProjectionTypesInitializer).Assembly); + } +} diff --git a/src/Tests/UnitTest/UnitTest.csproj b/src/Tests/UnitTest/UnitTest.csproj index ffad185bf..02e8b9b2c 100644 --- a/src/Tests/UnitTest/UnitTest.csproj +++ b/src/Tests/UnitTest/UnitTest.csproj @@ -11,11 +11,12 @@ + - + diff --git a/src/WinRT.Runtime2/ABI/System/Boolean.cs b/src/WinRT.Runtime2/ABI/System/Boolean.cs index 0d95e5aae..d9df97c93 100644 --- a/src/WinRT.Runtime2/ABI/System/Boolean.cs +++ b/src/WinRT.Runtime2/ABI/System/Boolean.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Boolean", + target: typeof(ABI.System.Boolean), + trimTarget: typeof(bool))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Boolean), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Boolean")] +[WindowsRuntimeMappedType(typeof(bool))] +[WindowsRuntimeReferenceType(typeof(bool?))] [BooleanComWrappersMarshaller] file static class Boolean; diff --git a/src/WinRT.Runtime2/ABI/System/Byte.cs b/src/WinRT.Runtime2/ABI/System/Byte.cs index 93b4266de..2c77a64e4 100644 --- a/src/WinRT.Runtime2/ABI/System/Byte.cs +++ b/src/WinRT.Runtime2/ABI/System/Byte.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "UInt8", + target: typeof(ABI.System.Byte), + trimTarget: typeof(byte))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Byte), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("UInt8")] +[WindowsRuntimeMappedType(typeof(byte))] +[WindowsRuntimeReferenceType(typeof(byte?))] [ByteComWrappersMarshaller] file static class Byte; diff --git a/src/WinRT.Runtime2/ABI/System/Char.cs b/src/WinRT.Runtime2/ABI/System/Char.cs index bb5e3d069..4ff1ae205 100644 --- a/src/WinRT.Runtime2/ABI/System/Char.cs +++ b/src/WinRT.Runtime2/ABI/System/Char.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Char16", + target: typeof(ABI.System.Char), + trimTarget: typeof(char))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Char), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Char16")] +[WindowsRuntimeMappedType(typeof(char))] +[WindowsRuntimeReferenceType(typeof(char?))] [CharComWrappersMarshaller] file static class Char; diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs index 6d1699463..3e6d1098f 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs @@ -16,10 +16,33 @@ #pragma warning disable IDE0008, IDE1006 +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo", + target: typeof(ABI.System.ComponentModel.INotifyDataErrorInfo), + trimTarget: typeof(INotifyDataErrorInfo))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + +[assembly: TypeMapAssociation( + source: typeof(INotifyDataErrorInfo), + proxy: typeof(ABI.System.ComponentModel.INotifyDataErrorInfo))] + +[assembly: TypeMapAssociation( + source: typeof(INotifyDataErrorInfo), + proxy: typeof(ABI.System.ComponentModel.INotifyDataErrorInfoInterfaceImpl))] + namespace ABI.System.ComponentModel; /// -/// Marshaller for . +/// ABI type for . +/// +[WindowsRuntimeMappedMetadata("Microsoft.UI.Xaml.WinUIContract")] +[WindowsRuntimeMetadataTypeName("Microsoft.UI.Xaml.Data.INotifyDataErrorInfo")] +[WindowsRuntimeMappedType(typeof(global::System.ComponentModel.INotifyDataErrorInfo))] +file static class INotifyDataErrorInfo; + +/// +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -28,22 +51,22 @@ namespace ABI.System.ComponentModel; public static unsafe class INotifyDataErrorInfoMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(INotifyDataErrorInfo? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.ComponentModel.INotifyDataErrorInfo? value) { - return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged( + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged( value: value, iid: in WellKnownWindowsInterfaceIIDs.IID_INotifyDataErrorInfo); } /// - public static INotifyDataErrorInfo? ConvertToManaged(void* value) + public static global::System.ComponentModel.INotifyDataErrorInfo? ConvertToManaged(void* value) { - return (INotifyDataErrorInfo?)WindowsRuntimeObjectMarshaller.ConvertToManaged(value); + return (global::System.ComponentModel.INotifyDataErrorInfo?)WindowsRuntimeObjectMarshaller.ConvertToManaged(value); } } /// -/// Interop methods for . +/// Interop methods for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -52,7 +75,7 @@ public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(INotifyDataE public static unsafe class INotifyDataErrorInfoMethods { /// - /// The table for . + /// The table for . /// private static ConditionalWeakTable> ErrorsChangedTable { @@ -71,7 +94,7 @@ static ConditionalWeakTable + /// [MethodImpl(MethodImplOptions.NoInlining)] public static bool HasErrors(WindowsRuntimeObjectReference thisReference) { @@ -85,7 +108,7 @@ public static bool HasErrors(WindowsRuntimeObjectReference thisReference) return Unsafe.BitCast(result) != 0; } - /// + /// public static EventHandlerEventSource ErrorsChanged(WindowsRuntimeObject thisObject, WindowsRuntimeObjectReference thisReference) { [UnsafeAccessor(UnsafeAccessorKind.Constructor)] @@ -98,7 +121,7 @@ public static EventHandlerEventSource ErrorsChanged( factoryArgument: thisReference); } - /// + /// [MethodImpl(MethodImplOptions.NoInlining)] public static IEnumerable GetErrors(WindowsRuntimeObjectReference thisReference, string? propertyName) { @@ -131,7 +154,7 @@ public static IEnumerable GetErrors(WindowsRuntimeObjectReference thisReference, } /// -/// Binding type for . +/// Binding type for . /// [StructLayout(LayoutKind.Sequential)] internal unsafe struct INotifyDataErrorInfoVftbl @@ -149,7 +172,7 @@ internal unsafe struct INotifyDataErrorInfoVftbl } /// -/// The implementation. +/// The implementation. /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -158,7 +181,7 @@ internal unsafe struct INotifyDataErrorInfoVftbl public static unsafe class INotifyDataErrorInfoImpl { /// - /// The value for the managed implementation. + /// The value for the managed implementation. /// [FixedAddressValueType] private static readonly INotifyDataErrorInfoVftbl Vftbl; @@ -177,7 +200,7 @@ static INotifyDataErrorInfoImpl() } /// - /// Gets a pointer to the managed implementation. + /// Gets a pointer to the managed implementation. /// public static nint Vtable { @@ -186,15 +209,15 @@ public static nint Vtable } /// - /// The table for . + /// The table for . /// - private static ConditionalWeakTable>> ErrorsChanged + private static ConditionalWeakTable>> ErrorsChanged { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { [MethodImpl(MethodImplOptions.NoInlining)] - static ConditionalWeakTable>> MakeErrorsChanged() + static ConditionalWeakTable>> MakeErrorsChanged() { _ = Interlocked.CompareExchange(ref field, [], null); @@ -213,7 +236,7 @@ private static HRESULT get_HasErrors(void* thisPtr, bool* result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); *result = unboxedValue.HasErrors; @@ -233,7 +256,7 @@ private static HRESULT add_ErrorsChanged(void* thisPtr, void* handler, EventRegi try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); [UnsafeAccessor(UnsafeAccessorKind.StaticMethod)] static extern EventHandler? ConvertToManaged( @@ -260,7 +283,7 @@ private static HRESULT remove_ErrorsChanged(void* thisPtr, EventRegistrationToke { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); if (unboxedValue is not null && ErrorsChanged.TryGetValue(unboxedValue, out var table) && table.RemoveEventHandler(token, out EventHandler? managedHandler)) { @@ -283,7 +306,7 @@ private static HRESULT GetErrors(void* thisPtr, HSTRING propertyName, void** res try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); IEnumerable managedResult = unboxedValue.GetErrors(HStringMarshaller.ConvertToManaged(propertyName)); @@ -304,45 +327,45 @@ static extern WindowsRuntimeObjectReferenceValue ConvertToUnmanaged( } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] -file interface INotifyDataErrorInfoInterfaceImpl : INotifyDataErrorInfo +file interface INotifyDataErrorInfoInterfaceImpl : global::System.ComponentModel.INotifyDataErrorInfo { /// - event EventHandler? INotifyDataErrorInfo.ErrorsChanged + event EventHandler? global::System.ComponentModel.INotifyDataErrorInfo.ErrorsChanged { add { var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(INotifyDataErrorInfo).TypeHandle); + var thisReference = thisObject.GetObjectReferenceForInterface(typeof(global::System.ComponentModel.INotifyDataErrorInfo).TypeHandle); INotifyDataErrorInfoMethods.ErrorsChanged((WindowsRuntimeObject)this, thisReference).Subscribe(value); } remove { var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(INotifyDataErrorInfo).TypeHandle); + var thisReference = thisObject.GetObjectReferenceForInterface(typeof(global::System.ComponentModel.INotifyDataErrorInfo).TypeHandle); INotifyDataErrorInfoMethods.ErrorsChanged(thisObject, thisReference).Unsubscribe(value); } } /// - bool INotifyDataErrorInfo.HasErrors + bool global::System.ComponentModel.INotifyDataErrorInfo.HasErrors { get { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(INotifyDataErrorInfo).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.ComponentModel.INotifyDataErrorInfo).TypeHandle); return INotifyDataErrorInfoMethods.HasErrors(thisReference); } } /// - IEnumerable INotifyDataErrorInfo.GetErrors(string? propertyName) + IEnumerable global::System.ComponentModel.INotifyDataErrorInfo.GetErrors(string? propertyName) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(INotifyDataErrorInfo).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.ComponentModel.INotifyDataErrorInfo).TypeHandle); return INotifyDataErrorInfoMethods.GetErrors(thisReference, propertyName); } diff --git a/src/WinRT.Runtime2/ABI/System/DateTimeOffset.cs b/src/WinRT.Runtime2/ABI/System/DateTimeOffset.cs index 072cab0e5..6cc2676cc 100644 --- a/src/WinRT.Runtime2/ABI/System/DateTimeOffset.cs +++ b/src/WinRT.Runtime2/ABI/System/DateTimeOffset.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.DateTime", + target: typeof(ABI.System.DateTimeOffset), + trimTarget: typeof(DateTimeOffset))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.DateTimeOffset), @@ -28,7 +33,11 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.DateTime")] +[WindowsRuntimeMappedType(typeof(global::System.DateTimeOffset))] +[WindowsRuntimeReferenceType(typeof(global::System.DateTimeOffset?))] [DateTimeOffsetComWrappersMarshaller] [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, diff --git a/src/WinRT.Runtime2/ABI/System/Double.cs b/src/WinRT.Runtime2/ABI/System/Double.cs index e51cd15b4..691f09b6b 100644 --- a/src/WinRT.Runtime2/ABI/System/Double.cs +++ b/src/WinRT.Runtime2/ABI/System/Double.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Double", + target: typeof(ABI.System.Double), + trimTarget: typeof(double))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Double), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Double")] +[WindowsRuntimeMappedType(typeof(double))] +[WindowsRuntimeReferenceType(typeof(double?))] [DoubleComWrappersMarshaller] file static class Double; diff --git a/src/WinRT.Runtime2/ABI/System/EventHandler.cs b/src/WinRT.Runtime2/ABI/System/EventHandler.cs index 0e8336d1f..b1364542b 100644 --- a/src/WinRT.Runtime2/ABI/System/EventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/EventHandler.cs @@ -38,6 +38,7 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference>")] [EventHandlerComWrappersMarshaller] file static class EventHandler; diff --git a/src/WinRT.Runtime2/ABI/System/Exception.cs b/src/WinRT.Runtime2/ABI/System/Exception.cs index e15674e1a..47e96d4c6 100644 --- a/src/WinRT.Runtime2/ABI/System/Exception.cs +++ b/src/WinRT.Runtime2/ABI/System/Exception.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.HResult", + target: typeof(ABI.System.Exception), + trimTarget: typeof(Exception))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Exception), @@ -28,7 +33,10 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.HResult")] +[WindowsRuntimeMappedType(typeof(global::System.Exception))] [ExceptionComWrappersMarshaller] [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, diff --git a/src/WinRT.Runtime2/ABI/System/Guid.cs b/src/WinRT.Runtime2/ABI/System/Guid.cs index c6876e054..1d799070c 100644 --- a/src/WinRT.Runtime2/ABI/System/Guid.cs +++ b/src/WinRT.Runtime2/ABI/System/Guid.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE0008, IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Guid", + target: typeof(ABI.System.Guid), + trimTarget: typeof(Guid))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Guid), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Guid")] +[WindowsRuntimeMappedType(typeof(global::System.Guid))] +[WindowsRuntimeReferenceType(typeof(global::System.Guid?))] [GuidComWrappersMarshaller] file static class Guid; diff --git a/src/WinRT.Runtime2/ABI/System/IDisposable.cs b/src/WinRT.Runtime2/ABI/System/IDisposable.cs index c57f72f9e..b5af6e7cf 100644 --- a/src/WinRT.Runtime2/ABI/System/IDisposable.cs +++ b/src/WinRT.Runtime2/ABI/System/IDisposable.cs @@ -13,10 +13,33 @@ #pragma warning disable IDE0008 +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.IClosable", + target: typeof(ABI.System.IDisposable), + trimTarget: typeof(IDisposable))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + +[assembly: TypeMapAssociation( + source: typeof(IDisposable), + proxy: typeof(ABI.System.IDisposable))] + +[assembly: TypeMapAssociation( + source: typeof(IDisposable), + proxy: typeof(ABI.System.IDisposableInterfaceImpl))] + namespace ABI.System; /// -/// Marshaller for . +/// ABI type for . +/// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.IClosable")] +[WindowsRuntimeMappedType(typeof(global::System.IDisposable))] +file static class IDisposable; + +/// +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -25,20 +48,20 @@ namespace ABI.System; public static unsafe class IDisposableMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IDisposable? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.IDisposable? value) { - return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IClosable); + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IClosable); } /// - public static IDisposable? ConvertToManaged(void* value) + public static global::System.IDisposable? ConvertToManaged(void* value) { - return (IDisposable?)WindowsRuntimeObjectMarshaller.ConvertToManaged(value); + return (global::System.IDisposable?)WindowsRuntimeObjectMarshaller.ConvertToManaged(value); } } /// -/// Interop methods for . +/// Interop methods for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -46,7 +69,7 @@ public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IDisposable? [EditorBrowsable(EditorBrowsableState.Never)] public static unsafe class IDisposableMethods { - /// + /// [MethodImpl(MethodImplOptions.NoInlining)] public static void Dispose(WindowsRuntimeObjectReference thisReference) { @@ -59,7 +82,7 @@ public static void Dispose(WindowsRuntimeObjectReference thisReference) } /// -/// Binding type for . +/// Binding type for . /// [StructLayout(LayoutKind.Sequential)] internal unsafe struct IDisposableVftbl @@ -74,7 +97,7 @@ internal unsafe struct IDisposableVftbl } /// -/// The implementation. +/// The implementation. /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -83,7 +106,7 @@ internal unsafe struct IDisposableVftbl public static unsafe class IDisposableImpl { /// - /// The value for the managed implementation. + /// The value for the managed implementation. /// [FixedAddressValueType] private static readonly IDisposableVftbl Vftbl; @@ -99,7 +122,7 @@ static IDisposableImpl() } /// - /// Gets a pointer to the managed implementation. + /// Gets a pointer to the managed implementation. /// public static nint Vtable { @@ -113,7 +136,7 @@ private static HRESULT Close(void* thisPtr) { try { - ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr).Dispose(); + ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr).Dispose(); return WellKnownErrorCodes.S_OK; } @@ -125,15 +148,17 @@ private static HRESULT Close(void* thisPtr) } /// -/// The implementation for . +/// The implementation for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] +[WindowsRuntimeClassName("Windows.Foundation.IClosable")] [DynamicInterfaceCastableImplementation] -file interface IDisposableInterfaceImpl : IDisposable +file interface IDisposableInterfaceImpl : global::System.IDisposable { /// - void IDisposable.Dispose() + void global::System.IDisposable.Dispose() { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IDisposable).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.IDisposable).TypeHandle); IDisposableMethods.Dispose(thisReference); } diff --git a/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs b/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs index d38df50ab..2f00a707c 100644 --- a/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs +++ b/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs @@ -13,10 +13,33 @@ #pragma warning disable IDE0008 +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Microsoft.UI.Xaml.IXamlServiceProvider", + target: typeof(ABI.System.IServiceProvider), + trimTarget: typeof(IServiceProvider))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + +[assembly: TypeMapAssociation( + source: typeof(IServiceProvider), + proxy: typeof(ABI.System.IServiceProvider))] + +[assembly: TypeMapAssociation( + source: typeof(IServiceProvider), + proxy: typeof(ABI.System.IServiceProviderInterfaceImpl))] + namespace ABI.System; /// -/// Marshaller for . +/// ABI type for . +/// +[WindowsRuntimeMappedMetadata("Microsoft.UI.Xaml.WinUIContract")] +[WindowsRuntimeMetadataTypeName("Microsoft.UI.Xaml.IXamlServiceProvider")] +[WindowsRuntimeMappedType(typeof(global::System.IServiceProvider))] +file static class IServiceProvider; + +/// +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -25,20 +48,20 @@ namespace ABI.System; public static unsafe class IServiceProviderMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IServiceProvider? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.IServiceProvider? value) { - return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IXamlServiceProvider); + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IXamlServiceProvider); } /// - public static IServiceProvider? ConvertToManaged(void* value) + public static global::System.IServiceProvider? ConvertToManaged(void* value) { - return (IServiceProvider?)WindowsRuntimeObjectMarshaller.ConvertToManaged(value); + return (global::System.IServiceProvider?)WindowsRuntimeObjectMarshaller.ConvertToManaged(value); } } /// -/// Interop methods for . +/// Interop methods for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -46,7 +69,7 @@ public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IServiceProv [EditorBrowsable(EditorBrowsableState.Never)] public static unsafe class IServiceProviderMethods { - /// + /// [MethodImpl(MethodImplOptions.NoInlining)] public static object? GetService(WindowsRuntimeObjectReference thisReference, global::System.Type serviceType) { @@ -74,7 +97,7 @@ public static unsafe class IServiceProviderMethods } /// -/// Binding type for . +/// Binding type for . /// [StructLayout(LayoutKind.Sequential)] internal unsafe struct IServiceProviderVftbl @@ -89,7 +112,7 @@ internal unsafe struct IServiceProviderVftbl } /// -/// The implementation. +/// The implementation. /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -98,7 +121,7 @@ internal unsafe struct IServiceProviderVftbl public static unsafe class IServiceProviderImpl { /// - /// The value for the managed implementation. + /// The value for the managed implementation. /// [FixedAddressValueType] private static readonly IServiceProviderVftbl Vftbl; @@ -114,7 +137,7 @@ static IServiceProviderImpl() } /// - /// Gets a pointer to the managed implementation. + /// Gets a pointer to the managed implementation. /// public static nint Vtable { @@ -133,7 +156,7 @@ private static HRESULT GetService(void* thisPtr, Type serviceType, void** result try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); global::System.Type? managedType = TypeMarshaller.ConvertToManaged(serviceType); @@ -157,15 +180,15 @@ private static HRESULT GetService(void* thisPtr, Type serviceType, void** result } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] -file interface IServiceProviderInterfaceImpl : IServiceProvider +file interface IServiceProviderInterfaceImpl : global::System.IServiceProvider { /// - object? IServiceProvider.GetService(global::System.Type serviceType) + object? global::System.IServiceProvider.GetService(global::System.Type serviceType) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IServiceProvider).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.IServiceProvider).TypeHandle); return IServiceProviderMethods.GetService(thisReference, serviceType); } diff --git a/src/WinRT.Runtime2/ABI/System/Int16.cs b/src/WinRT.Runtime2/ABI/System/Int16.cs index 629fe5096..8e791b62f 100644 --- a/src/WinRT.Runtime2/ABI/System/Int16.cs +++ b/src/WinRT.Runtime2/ABI/System/Int16.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Int16", + target: typeof(ABI.System.Int16), + trimTarget: typeof(short))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Int16), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Int16")] +[WindowsRuntimeMappedType(typeof(short))] +[WindowsRuntimeReferenceType(typeof(short?))] [Int16ComWrappersMarshaller] file static class Int16; diff --git a/src/WinRT.Runtime2/ABI/System/Int32.cs b/src/WinRT.Runtime2/ABI/System/Int32.cs index 4bf5f5660..209bcca17 100644 --- a/src/WinRT.Runtime2/ABI/System/Int32.cs +++ b/src/WinRT.Runtime2/ABI/System/Int32.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Int32", + target: typeof(ABI.System.Int32), + trimTarget: typeof(int))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Int32), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Int32")] +[WindowsRuntimeMappedType(typeof(int))] +[WindowsRuntimeReferenceType(typeof(int?))] [Int32ComWrappersMarshaller] file static class Int32; diff --git a/src/WinRT.Runtime2/ABI/System/Int64.cs b/src/WinRT.Runtime2/ABI/System/Int64.cs index e283e2245..c302b1d34 100644 --- a/src/WinRT.Runtime2/ABI/System/Int64.cs +++ b/src/WinRT.Runtime2/ABI/System/Int64.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Int64", + target: typeof(ABI.System.Int64), + trimTarget: typeof(long))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Int64), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Int64")] +[WindowsRuntimeMappedType(typeof(long))] +[WindowsRuntimeReferenceType(typeof(long?))] [Int64ComWrappersMarshaller] file static class Int64; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Matrix3x2.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Matrix3x2.cs index 49ca34d37..57625efca 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Matrix3x2.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Matrix3x2.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Matrix3x2", + target: typeof(ABI.System.Numerics.Matrix3x2), + trimTarget: typeof(Matrix3x2))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Matrix3x2), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Matrix3x2")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Matrix3x2))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Matrix3x2?))] [Matrix3x2ComWrappersMarshaller] file static class Matrix3x2; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Matrix4x4.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Matrix4x4.cs index b33b52e9c..b72a81daa 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Matrix4x4.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Matrix4x4.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Matrix4x4", + target: typeof(ABI.System.Numerics.Matrix4x4), + trimTarget: typeof(Matrix4x4))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Matrix4x4), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Matrix4x4")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Matrix4x4))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Matrix4x4?))] [Matrix4x4ComWrappersMarshaller] file static class Matrix4x4; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Plane.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Plane.cs index be76efb0e..8b4c49e9e 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Plane.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Plane.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Plane", + target: typeof(ABI.System.Numerics.Plane), + trimTarget: typeof(Plane))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Plane), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Plane")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Plane))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Plane?))] [PlaneComWrappersMarshaller] file static class Plane; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Quaternion.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Quaternion.cs index 0e41448a9..4e2f1b5d1 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Quaternion.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Quaternion.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Quaternion", + target: typeof(ABI.System.Numerics.Quaternion), + trimTarget: typeof(Quaternion))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Quaternion), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Quaternion")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Quaternion))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Quaternion?))] [QuaternionComWrappersMarshaller] file static class Quaternion; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Vector2.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Vector2.cs index 40ce67b61..c240304e9 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Vector2.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Vector2.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Vector2", + target: typeof(ABI.System.Numerics.Vector2), + trimTarget: typeof(Vector2))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Vector2), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Vector2")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Vector2))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Vector2?))] [Vector2ComWrappersMarshaller] file static class Vector2; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Vector3.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Vector3.cs index 34aefc8fd..ef1475ed6 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Vector3.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Vector3.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Vector3", + target: typeof(ABI.System.Numerics.Vector3), + trimTarget: typeof(Vector3))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Vector3), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Vector3")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Vector3))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Vector3?))] [Vector3ComWrappersMarshaller] file static class Vector3; diff --git a/src/WinRT.Runtime2/ABI/System/Numerics/Vector4.cs b/src/WinRT.Runtime2/ABI/System/Numerics/Vector4.cs index d37b57fec..820bd4259 100644 --- a/src/WinRT.Runtime2/ABI/System/Numerics/Vector4.cs +++ b/src/WinRT.Runtime2/ABI/System/Numerics/Vector4.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Numerics.Vector4", + target: typeof(ABI.System.Numerics.Vector4), + trimTarget: typeof(Vector4))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Numerics.Vector4), @@ -29,7 +34,11 @@ namespace ABI.System.Numerics; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Numerics.Vector4")] +[WindowsRuntimeMappedType(typeof(global::System.Numerics.Vector4))] +[WindowsRuntimeReferenceType(typeof(global::System.Numerics.Vector4?))] [Vector4ComWrappersMarshaller] file static class Vector4; diff --git a/src/WinRT.Runtime2/ABI/System/Object.cs b/src/WinRT.Runtime2/ABI/System/Object.cs index 94b486110..ecfd3b21e 100644 --- a/src/WinRT.Runtime2/ABI/System/Object.cs +++ b/src/WinRT.Runtime2/ABI/System/Object.cs @@ -7,6 +7,13 @@ using WindowsRuntime.InteropServices; using static System.Runtime.InteropServices.ComWrappers; +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Object", + target: typeof(ABI.System.Object), + trimTarget: typeof(object))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + [assembly: TypeMapAssociation(typeof(object), typeof(ABI.System.Object))] namespace ABI.System; @@ -14,7 +21,9 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Object")] +[WindowsRuntimeMappedType(typeof(object))] [ObjectComWrappersMarshaller] file static class Object; diff --git a/src/WinRT.Runtime2/ABI/System/Single.cs b/src/WinRT.Runtime2/ABI/System/Single.cs index 7565aed65..39d60c417 100644 --- a/src/WinRT.Runtime2/ABI/System/Single.cs +++ b/src/WinRT.Runtime2/ABI/System/Single.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Single", + target: typeof(ABI.System.Single), + trimTarget: typeof(float))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Single), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Single")] +[WindowsRuntimeMappedType(typeof(float))] +[WindowsRuntimeReferenceType(typeof(float?))] [SingleComWrappersMarshaller] file static class Single; diff --git a/src/WinRT.Runtime2/ABI/System/String.cs b/src/WinRT.Runtime2/ABI/System/String.cs index 201a747f1..4747c680d 100644 --- a/src/WinRT.Runtime2/ABI/System/String.cs +++ b/src/WinRT.Runtime2/ABI/System/String.cs @@ -15,6 +15,11 @@ #pragma warning disable IDE0008, IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "String", + target: typeof(ABI.System.String), + trimTarget: typeof(string))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.String), @@ -28,7 +33,10 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("String")] +[WindowsRuntimeMappedType(typeof(string))] [StringComWrappersMarshaller] file static class String; diff --git a/src/WinRT.Runtime2/ABI/System/TimeSpan.cs b/src/WinRT.Runtime2/ABI/System/TimeSpan.cs index 2b6bdf828..326d4502c 100644 --- a/src/WinRT.Runtime2/ABI/System/TimeSpan.cs +++ b/src/WinRT.Runtime2/ABI/System/TimeSpan.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.TimeSpan", + target: typeof(ABI.System.TimeSpan), + trimTarget: typeof(TimeSpan))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.TimeSpan), @@ -28,7 +33,11 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.TimeSpan")] +[WindowsRuntimeMappedType(typeof(global::System.TimeSpan))] +[WindowsRuntimeReferenceType(typeof(global::System.TimeSpan?))] [TimeSpanComWrappersMarshaller] [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, diff --git a/src/WinRT.Runtime2/ABI/System/Type.cs b/src/WinRT.Runtime2/ABI/System/Type.cs index 9e8c9deec..eb33a41a6 100644 --- a/src/WinRT.Runtime2/ABI/System/Type.cs +++ b/src/WinRT.Runtime2/ABI/System/Type.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -20,6 +21,11 @@ #pragma warning disable IDE0008, IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.UI.Xaml.Interop.TypeName", + target: typeof(ABI.System.Type), + trimTarget: typeof(Type))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.Type), @@ -34,7 +40,10 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.UI.Xaml.Interop.TypeName")] +[WindowsRuntimeMappedType(typeof(global::System.Type))] [TypeComWrappersMarshaller] [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -92,10 +101,150 @@ public static void ConvertToUnmanagedUnsafe(global::System.Type value, out TypeR { ArgumentNullException.ThrowIfNull(value); - string abiName = ""; // TODO - TypeKind kind = default; // TODO + // Special case for 'NoMetadataTypeInfo' instances, which can only be obtained + // from previous calls to 'ConvertToManaged' for types that had been trimmed. + if (value is NoMetadataTypeInfo noMetadataTypeInfo) + { + reference = new TypeReference { Name = noMetadataTypeInfo.FullName, Kind = TypeKind.Metadata }; + + return; + } + + // We need special handling for 'Nullable' values. If we have one, we want to use the underlying type + // for the lookup, because the nullable version would not have any entries in the type map. Additionally, + // we want to skip the metadata table lookup, as that would give us the actual metadata type name for the + // underlying type. Instead, for 'Nullable' values we need the runtime class name, which in this case + // would be the 'IReference' type name for boxed instances of this type. + global::System.Type? nullableUnderlyingType = Nullable.GetUnderlyingType(value); + + // For projected types (not custom-mapped, but possibly manually projected, like e.g. 'IAsyncInfo'), we + // can always just use the fully qualified type name (as it will always match the one in the .winmd file). + // We can check if a given type matches this by just checking whether it has '[WindowsRuntimeMetadata]'. + // Note that we're intentionally skipping generic types, as for those we need the 'cswinrtgen' info. + // Additionally, this path isn't taken if we have a nullable value type, which avoids the lookup too. + if (nullableUnderlyingType is null && !value.IsGenericType && value.IsDefined(typeof(WindowsRuntimeMetadataAttribute))) + { + reference = new TypeReference { Name = value.FullName, Kind = TypeKind.Metadata }; + + return; + } + + // TODO: for generic interfaces, 'cswinrtgen' will emit an entry with the metadata name in the metadata type map. + + // Use the metadata info lookup first to handle custom-mapped interface types. These would not have a proxy + // type map entry for normal marshalling (because they're interfaces), and they would also not show up as + // being projected types from there. So we handle them here first to get the right metadata type name. + if (nullableUnderlyingType is null && WindowsRuntimeMetadataInfo.TryGetInfo(value, out WindowsRuntimeMetadataInfo? metadataInfo)) + { + reference = new TypeReference { Name = metadataInfo.GetMetadataTypeName(), Kind = TypeKind.Metadata }; + + return; + } + + // Special case 'Exception' types, since we also need to handle all derived types (e.g. user-defined) + if (value.IsAssignableTo(typeof(global::System.Exception))) + { + reference = new TypeReference { Name = "Windows.Foundation.HResult", Kind = TypeKind.Metadata }; + + return; + } + + // Special case 'Type' as well, for the same reason (e.g. 'typeof(Foo)' would return a 'RuntimeType' instance) + if (value.IsAssignableTo(typeof(global::System.Type))) + { + reference = new TypeReference { Name = "Windows.UI.Xaml.Interop.TypeName", Kind = TypeKind.Metadata }; + + return; + } - reference = new TypeReference { Name = abiName, Kind = kind }; + global::System.Type typeOrUnderlyingType = nullableUnderlyingType ?? value; + + // Use the marshalling info lookup to detect projected or custom-mapped Windows Runtime types. + // If we have an underlying nullable type, we use that for the lookup instead of the input type. + if (WindowsRuntimeMarshallingInfo.TryGetInfo(typeOrUnderlyingType, out WindowsRuntimeMarshallingInfo? marshallingInfo) && marshallingInfo.IsMetadataType) + { + // For primitive types, we always report 'TypeKind.Primitive'. This means that some + // types that are C# primitives (e.g. 'sbyte') will be reported as such, even though + // they're not Windows Runtime types. This is expected, and matches C++/WinRT as well. + TypeKind kind = value.IsPrimitive + ? TypeKind.Primitive + : TypeKind.Metadata; + + // We need special handling for several cases that represent non-boxed types + if (nullableUnderlyingType is null) + { + // Special case primitive types that are of types that can be boxed. That is, if the input type is not + // some 'Nullable' type, check if we have an explicit metadata type name, and use that if so. This + // will ensure that e.g. 'typeof(int)' will report 'Int32', not 'Windows.Foundation.IReference'. + if (marshallingInfo.TryGetMetadataTypeName(out string? metadataTypeName)) + { + reference = new TypeReference { Name = metadataTypeName, Kind = kind }; + + return; + } + + // If we don't have a metadata type name, check if we have a value type or a delegate type. + // Note that this path can only be reached for those if either is true: + // - The value type is not generic (otherwise the proxy type would've had the metadata name) + // - The delegate is not generic (for the same reason as above, or we would've had a proxy) + // So in either case, we can just use the fully qualified type name here, which will match + // the .winmd type name. We don't have to worry about custom-mapped types here, as those will + // have already been handled above. This special case ensures we don't get the boxed type name. + if (typeOrUnderlyingType.IsValueType || + typeOrUnderlyingType.IsAssignableTo(typeof(Delegate))) + { + reference = new TypeReference { Name = typeOrUnderlyingType.FullName, Kind = kind }; + + return; + } + + // TODO: Skip 'KVP<,>'. + } + + // We don't support marshalling a 'KeyValuePair<,>?' type, as that is not a valid Windows Runtime + // type (since 'KeyValuePair<,>' is an interface in the Windows Runtime type system. So if we get + // one, we just treat it like any other custom (e.g. user-defined) types instead. + if (nullableUnderlyingType is not null && + nullableUnderlyingType.IsValueType && + nullableUnderlyingType.IsGenericType && + nullableUnderlyingType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + goto CustomType; + } + + // If we don't have a metadata type name, try to get the runtime class name. This will handle + // cases such as constructed 'Nullable' types, which will report their boxed type name. + if (marshallingInfo.TryGetRuntimeClassName(out string? runtimeClassName)) + { + reference = new TypeReference { Name = runtimeClassName, Kind = kind }; + + return; + } + + // Otherwise, use the type name directly. This will handle all remaining cases, such as projected + // runtime classes and interface types. For all of those, the projected type name will be correct. + reference = new TypeReference { Name = typeOrUnderlyingType.FullName, Kind = kind }; + + return; + } + + // For primitive types, we always report 'TypeKind.Primitive'. This means that some + // types that are C# primitives (e.g. 'sbyte') will be reported as such, even though + // they're not Windows Runtime types. This is expected, and matches C++/WinRT as well. + // Note that all primitive types that are Windows Runtime types should have been handled + // by the case above already. This path just ensures the other ones are not treated as + // custom types, which they would be otherwise, since they don't have marshalling info. + if (value.IsPrimitive) + { + reference = new TypeReference { Name = value.FullName, Kind = TypeKind.Primitive }; + + return; + } + + CustomType: + + // All other cases are treated as custom types (e.g. user-defined types) + reference = new TypeReference { Name = value.AssemblyQualifiedName, Kind = TypeKind.Custom }; } /// @@ -122,7 +271,76 @@ public static void ConvertToUnmanagedUnsafe(global::System.Type value, out TypeR return global::System.Type.GetType(typeName.ToString()); } - global::System.Type? type = null; // TODO + // Handle special-cases metadata types after checking the type kind + if (value.Kind is TypeKind.Metadata) + { + // For any 'HResult' type, we return 'Exception'. If a user had marshalled + // any derived exception type, that will not actually round-trip exactly. + // This is expected and by design. We don't try to preserve the original. + if (typeName.SequenceEqual("Windows.Foundation.HResult")) + { + return typeof(global::System.Exception); + } + + // Same as above for 'Type'. We intentionally don't perfectly round-trip. + if (typeName.SequenceEqual("Windows.UI.Xaml.Interop.TypeName")) + { + return typeof(global::System.Type); + } + } + + global::System.Type? type = null; + + // TODO: put type map entries for non-generic interfaces in the metadata type map. + // This also needs to have entries for all value types and delegate types + + // If the type was handled by the metadata lookup, get the public type from there + if (WindowsRuntimeMetadataInfo.TryGetInfo(typeName, out WindowsRuntimeMetadataInfo? metadataInfo)) + { + type = metadataInfo.PublicType; + } + else if (WindowsRuntimeMarshallingInfo.TryGetInfo(typeName, out WindowsRuntimeMarshallingInfo? marshallingInfo)) + { + // Otherwise, try to retrieve the marshalling info for the input type name. + // This will work for both 'Primitive' and 'Metadata' types, same as above. + global::System.Type publicType = marshallingInfo.PublicType; + + // If we got here, it means we have some 'IReference' instance with the + // element type being some delegate, exception, or 'Type' type. Because we + // only support marshalling them as 'TypeName' by value (not references), + // we're intentionally always just returning missing metadata for them. + if (publicType.IsAssignableTo(typeof(Delegate)) || + publicType.IsAssignableTo(typeof(global::System.Exception)) || + publicType.IsAssignableTo(typeof(global::System.Type))) + { + return NoMetadataTypeInfo.GetOrCreate(typeName); + } + + // Special case 'KeyValuePair<,>' instances, where we always want to return the public type + // directly here, and not its nullable version. This is because 'KeyValuePair<,>' is an + // interface type in the Windows Runtime type system, so the type name we got here from + // the marshalling type map wouldn't actually represent an 'IReference' instantiation. + if (publicType.IsValueType && + publicType.IsGenericType && + publicType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + type = publicType; + } + else + { + // For value types, we get the reference type (i.e. the constructed 'Nullable' type) + // from the marshalling info. This will perform a lookup for '[WindowsRuntimeReferenceType]'. + type = publicType.IsValueType ? marshallingInfo.ReferenceType : publicType; + } + } + + // Handle the case of C# primitive types that are not Windows Runtime types. + // For instance, 'System.SByte' could be passed, which would not be found + // in the previous lookup. We still want to be able to round-trip such values. + if (type is null && value.Kind is TypeKind.Primitive && typeName.StartsWith("System.", StringComparison.Ordinal)) + { + return global::System.Type.GetType(typeName.ToString()); + } // If the target type is a projected type that has been trimmed, we can return a special type. // This is mostly used by the XAML metadata provider. The type itself should never actually be diff --git a/src/WinRT.Runtime2/ABI/System/UInt16.cs b/src/WinRT.Runtime2/ABI/System/UInt16.cs index 4612b0a17..115c03c99 100644 --- a/src/WinRT.Runtime2/ABI/System/UInt16.cs +++ b/src/WinRT.Runtime2/ABI/System/UInt16.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "UInt16", + target: typeof(ABI.System.UInt16), + trimTarget: typeof(ushort))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.UInt16), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("UInt16")] +[WindowsRuntimeMappedType(typeof(ushort))] +[WindowsRuntimeReferenceType(typeof(ushort?))] [UInt16ComWrappersMarshaller] file static class UInt16; diff --git a/src/WinRT.Runtime2/ABI/System/UInt32.cs b/src/WinRT.Runtime2/ABI/System/UInt32.cs index f1ed50043..db1058693 100644 --- a/src/WinRT.Runtime2/ABI/System/UInt32.cs +++ b/src/WinRT.Runtime2/ABI/System/UInt32.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "UInt32", + target: typeof(ABI.System.UInt32), + trimTarget: typeof(uint))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.UInt32), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("UInt32")] +[WindowsRuntimeMappedType(typeof(uint))] +[WindowsRuntimeReferenceType(typeof(uint?))] [UInt32ComWrappersMarshaller] file static class UInt32; diff --git a/src/WinRT.Runtime2/ABI/System/UInt64.cs b/src/WinRT.Runtime2/ABI/System/UInt64.cs index dc33f6b0c..afd2e36c2 100644 --- a/src/WinRT.Runtime2/ABI/System/UInt64.cs +++ b/src/WinRT.Runtime2/ABI/System/UInt64.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "UInt64", + target: typeof(ABI.System.UInt64), + trimTarget: typeof(ulong))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(ABI.System.UInt64), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("UInt64")] +[WindowsRuntimeMappedType(typeof(ulong))] +[WindowsRuntimeReferenceType(typeof(ulong?))] [UInt64ComWrappersMarshaller] file static class UInt64; diff --git a/src/WinRT.Runtime2/ABI/System/Uri.cs b/src/WinRT.Runtime2/ABI/System/Uri.cs index 08691d722..ed0659fc8 100644 --- a/src/WinRT.Runtime2/ABI/System/Uri.cs +++ b/src/WinRT.Runtime2/ABI/System/Uri.cs @@ -26,7 +26,9 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.Uri")] +[WindowsRuntimeMappedType(typeof(global::System.Uri))] [UriComWrappersMarshaller] file static class Uri; diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs index 5d5b8d1a5..e06b41ddd 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE0008, IDE1006 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.AsyncActionCompletedHandler", + target: typeof(AsyncActionCompletedHandler), + trimTarget: typeof(AsyncActionCompletedHandler))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(AsyncActionCompletedHandler), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/CollectionChange.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/CollectionChange.cs index 09ab034da..68b065fbc 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/CollectionChange.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/CollectionChange.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Collections.CollectionChange", + target: typeof(CollectionChange), + trimTarget: typeof(CollectionChange))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(CollectionChange), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs index 39546c8b1..10dc34211 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs @@ -14,7 +14,18 @@ #pragma warning disable IDE0008, IDE1006 -namespace ABI.System.ComponentModel; +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Collections.IVectorChangedEventArgs", + target: typeof(IVectorChangedEventArgs), + trimTarget: typeof(IVectorChangedEventArgs))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + +[assembly: TypeMapAssociation( + source: typeof(IVectorChangedEventArgs), + proxy: typeof(ABI.Windows.Foundation.Collections.IVectorChangedEventArgsInterfaceImpl))] + +namespace ABI.Windows.Foundation.Collections; /// /// Marshaller for . @@ -141,7 +152,7 @@ private static HRESULT get_CollectionChange(void* thisPtr, CollectionChange* res return WellKnownErrorCodes.S_OK; } - catch (global::System.Exception e) + catch (Exception e) { return RestrictedErrorInfoExceptionMarshaller.ConvertToUnmanaged(e); } @@ -159,7 +170,7 @@ private static HRESULT get_Index(void* thisPtr, uint* result) return WellKnownErrorCodes.S_OK; } - catch (global::System.Exception e) + catch (Exception e) { return RestrictedErrorInfoExceptionMarshaller.ConvertToUnmanaged(e); } diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs index ccf338616..ce93a5060 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs @@ -14,6 +14,13 @@ #pragma warning disable IDE0008, IDE1006, CA2256 +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.IAsyncAction", + target: typeof(IAsyncInfo), + trimTarget: typeof(IAsyncAction))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + [assembly: TypeMapAssociation( source: typeof(IAsyncAction), proxy: typeof(ABI.Windows.Foundation.IAsyncActionInterfaceImpl))] diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs index c4f6832db..1d9384d2a 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs @@ -13,6 +13,17 @@ #pragma warning disable IDE0008, IDE1006 +#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.IAsyncInfo", + target: typeof(IAsyncInfo), + trimTarget: typeof(IAsyncInfo))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + +[assembly: TypeMapAssociation( + source: typeof(IAsyncInfo), + proxy: typeof(ABI.Windows.Foundation.IAsyncInfoInterfaceImpl))] + namespace ABI.Windows.Foundation; /// diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Point.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Point.cs index e4e069314..46501138c 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/Point.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/Point.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Point", + target: typeof(Point), + trimTarget: typeof(Point))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(Point), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Rect.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Rect.cs index 017a7ee92..b4a72cb80 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/Rect.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/Rect.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Rect", + target: typeof(Rect), + trimTarget: typeof(Rect))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(Rect), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Size.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Size.cs index 2e0aa9ce7..8ce9f4c19 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/Size.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/Size.cs @@ -14,6 +14,11 @@ #pragma warning disable IDE1006, CA1416 #pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code +[assembly: TypeMap( + value: "Windows.Foundation.Size", + target: typeof(Size), + trimTarget: typeof(Size))] + [assembly: TypeMap( value: "Windows.Foundation.IReference", target: typeof(Size), diff --git a/src/WinRT.Runtime2/Attributes/WindowsRuntimeMappedMetadataAttribute.cs b/src/WinRT.Runtime2/Attributes/WindowsRuntimeMappedMetadataAttribute.cs new file mode 100644 index 000000000..abec34fd5 --- /dev/null +++ b/src/WinRT.Runtime2/Attributes/WindowsRuntimeMappedMetadataAttribute.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime; + +/// +/// Indicates the mapped source Windows Runtime metadata file (.winmd) that a given custom-mapped type is from. +/// +[AttributeUsage( + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Interface | + AttributeTargets.Delegate, + AllowMultiple = false, + Inherited = false)] +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed class WindowsRuntimeMappedMetadataAttribute : Attribute +{ + /// + /// Creates a new instance with the specified parameters. + /// + /// The name of the mapped source Windows Runtime metadata file (.winmd) that the current custom-mapped type is from. + public WindowsRuntimeMappedMetadataAttribute(string name) + { + Name = name; + } + + /// + /// Gets the name of the mapped source Windows Runtime metadata file (.winmd) that the current custom-mapped type is from. + /// + public string Name { get; } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/Attributes/WindowsRuntimeMetadataTypeNameAttribute.cs b/src/WinRT.Runtime2/Attributes/WindowsRuntimeMetadataTypeNameAttribute.cs new file mode 100644 index 000000000..352cae8da --- /dev/null +++ b/src/WinRT.Runtime2/Attributes/WindowsRuntimeMetadataTypeNameAttribute.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime; + +/// +/// Indicates the metadata type class name to use for types exposed to the Windows Runtime. +/// +/// +/// +/// This attribute is only needed for the marshalling infrastructure for custom-mapped types. +/// +/// +/// It differs from in that it represents the metadata name of +/// the type itself, not the runtime class name for when an instance is marshalled to native as an object. +/// For instance, when applied to value types it would contain their type name, not the IReference<T> name. +/// +/// +[AttributeUsage( + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Interface | + AttributeTargets.Delegate, + AllowMultiple = false, + Inherited = false)] +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed class WindowsRuntimeMetadataTypeNameAttribute : Attribute +{ + /// + /// Creates a new instance with the specified parameters. + /// + /// The metadata type name to use. + public WindowsRuntimeMetadataTypeNameAttribute(string metadataTypeName) + { + MetadataTypeName = metadataTypeName; + } + + /// + /// Gets the metadata type name for the current instance. + /// + public string MetadataTypeName { get; } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/Attributes/WindowsRuntimeReferenceTypeAttribute.cs b/src/WinRT.Runtime2/Attributes/WindowsRuntimeReferenceTypeAttribute.cs new file mode 100644 index 000000000..68f1a6e26 --- /dev/null +++ b/src/WinRT.Runtime2/Attributes/WindowsRuntimeReferenceTypeAttribute.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime; + +/// +/// Indicates the reference type associated to a given Windows Runtime value type. +/// +/// This attribute is only needed for the marshalling infrastructure. +[AttributeUsage( + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum, + AllowMultiple = false, + Inherited = false)] +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed class WindowsRuntimeReferenceTypeAttribute : Attribute +{ + /// + /// Creates a new instance with the specified parameters. + /// + /// The reference type (a constructed type) for the annotated type. + public WindowsRuntimeReferenceTypeAttribute(Type referenceType) + { + ReferenceType = referenceType; + } + + /// + /// Gets the reference type (a constructed type) for the annotated type. + /// + public Type ReferenceType { get; } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Events/EventRegistrationToken.cs b/src/WinRT.Runtime2/InteropServices/Events/EventRegistrationToken.cs index 34af098d3..57868f260 100644 --- a/src/WinRT.Runtime2/InteropServices/Events/EventRegistrationToken.cs +++ b/src/WinRT.Runtime2/InteropServices/Events/EventRegistrationToken.cs @@ -13,6 +13,7 @@ namespace WindowsRuntime.InteropServices; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeReferenceType(typeof(EventRegistrationToken?))] [ABI.WindowsRuntime.InteropServices.EventRegistrationTokenComWrappersMarshaller] public struct EventRegistrationToken : IEquatable { diff --git a/src/WinRT.Runtime2/InteropServices/ObjectReference/ContextAwareObjectReference.cs b/src/WinRT.Runtime2/InteropServices/ObjectReference/ContextAwareObjectReference.cs index cb3720428..21847dffc 100644 --- a/src/WinRT.Runtime2/InteropServices/ObjectReference/ContextAwareObjectReference.cs +++ b/src/WinRT.Runtime2/InteropServices/ObjectReference/ContextAwareObjectReference.cs @@ -132,7 +132,7 @@ static void InitializeAgileReference(object state) // trying again every time. To do this, we just set the field to a placeholder if it's still 'null'. _ = Interlocked.CompareExchange( location1: ref _agileReference, - value: PlaceholderNullAgileReference.Instance, + value: NullPlaceholder.Instance, comparand: null); // At this point we can return whatever the updated value is @@ -146,7 +146,7 @@ static void InitializeAgileReference(object state) // Check if we got the placeholder value, and return 'null' if so. // Otherwise, we can rely on the instance being an object reference. - return agileReference == PlaceholderNullAgileReference.Instance + return agileReference == NullPlaceholder.Instance ? null : Unsafe.As(agileReference); } @@ -302,15 +302,4 @@ private static class CachedContextsObjectReferenceFactory } } } -} - -/// -/// A placeholder object for . -/// -file static class PlaceholderNullAgileReference -{ - /// - /// The shared placeholder instance. - /// - public static object Instance = new(); } \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Placeholders/DynamicInterfaceCastableImplementationForwarderAttributePlaceholder.cs b/src/WinRT.Runtime2/InteropServices/Placeholders/DynamicInterfaceCastableImplementationForwarderAttributePlaceholder.cs new file mode 100644 index 000000000..df1a1dacb --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Placeholders/DynamicInterfaceCastableImplementationForwarderAttributePlaceholder.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace WindowsRuntime.InteropServices; + +/// +/// A placeholder type. +/// +internal sealed class DynamicInterfaceCastableImplementationForwarderAttributePlaceholder : DynamicInterfaceCastableImplementationForwarderAttribute +{ + /// + /// The shared placeholder instance. + /// + public static DynamicInterfaceCastableImplementationForwarderAttributePlaceholder Instance = new(); + + /// + public override bool TryGetImplementationType( + WindowsRuntimeObjectReference thisReference, + [NotNullWhen(true)] out WindowsRuntimeObjectReference? interfaceReference, + [NotNullWhen(true)] out Type? implementationType) + { + interfaceReference = null; + implementationType = null; + + return false; + } +} diff --git a/src/WinRT.Runtime2/InteropServices/Placeholders/WindowsRuntimeComWrappersMarshallerAttributePlaceholder.cs b/src/WinRT.Runtime2/InteropServices/Placeholders/WindowsRuntimeComWrappersMarshallerAttributePlaceholder.cs new file mode 100644 index 000000000..796157bcd --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Placeholders/WindowsRuntimeComWrappersMarshallerAttributePlaceholder.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Runtime.InteropServices; + +namespace WindowsRuntime.InteropServices; + +/// +/// A placeholder type. +/// +internal sealed unsafe class WindowsRuntimeComWrappersMarshallerAttributePlaceholder : WindowsRuntimeComWrappersMarshallerAttribute +{ + /// + /// The shared placeholder instance. + /// + public static readonly WindowsRuntimeComWrappersMarshallerAttributePlaceholder Instance = new(); + + /// + public override void* GetOrCreateComInterfaceForObject(object value) + { + return null; + } + + /// + public override ComWrappers.ComInterfaceEntry* ComputeVtables(out int count) + { + count = 0; + + return null; + } + + /// + public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) + { + wrapperFlags = CreatedWrapperFlags.None; + + return null!; + } +} diff --git a/src/WinRT.Runtime2/InteropServices/TypeMapGroups/WindowsRuntimeMetadataTypeMapGroup.cs b/src/WinRT.Runtime2/InteropServices/TypeMapGroups/WindowsRuntimeMetadataTypeMapGroup.cs new file mode 100644 index 000000000..59b512bf8 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/TypeMapGroups/WindowsRuntimeMetadataTypeMapGroup.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace WindowsRuntime.InteropServices; + +/// +/// The type map group placeholder for all Windows Runtime types that need to support marshalling. +/// +/// +/// This type is only meant to be used as type map group for APIs. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public abstract class WindowsRuntimeMetadataTypeMapGroup +{ + /// + /// This type should never be instantiated (it just can't be static because it needs to be used as a type argument). + /// + private WindowsRuntimeMetadataTypeMapGroup() + { + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/TypeMapInfo/DynamicInterfaceCastableImplementationInfo.cs b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/DynamicInterfaceCastableImplementationInfo.cs index 40a39d19e..c8d68687c 100644 --- a/src/WinRT.Runtime2/InteropServices/TypeMapInfo/DynamicInterfaceCastableImplementationInfo.cs +++ b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/DynamicInterfaceCastableImplementationInfo.cs @@ -127,11 +127,11 @@ bool Load([NotNullWhen(true)] out DynamicInterfaceCastableImplementationForwarde { DynamicInterfaceCastableImplementationForwarderAttribute? value = ImplementationType.GetCustomAttribute(inherit: false); - value ??= PlaceholderDynamicInterfaceCastableImplementationForwarderAttribute.Instance; + value ??= DynamicInterfaceCastableImplementationForwarderAttributePlaceholder.Instance; _implementationForwarder = value; - if (value is not (null or PlaceholderDynamicInterfaceCastableImplementationForwarderAttribute)) + if (value is not (null or DynamicInterfaceCastableImplementationForwarderAttributePlaceholder)) { forwarder = value; @@ -148,7 +148,7 @@ bool Load([NotNullWhen(true)] out DynamicInterfaceCastableImplementationForwarde // We have a cached forwarder, so return it immediately if (value is not null) { - if (value is PlaceholderDynamicInterfaceCastableImplementationForwarderAttribute) + if (value is DynamicInterfaceCastableImplementationForwarderAttributePlaceholder) { forwarder = null; @@ -179,27 +179,4 @@ bool Load([NotNullWhen(true)] out DynamicInterfaceCastableImplementationForwarde // There's no '[DynamicCastableImplementation]' info for the provided interface type return null; } -} - -/// -/// A placeholder type. -/// -file sealed class PlaceholderDynamicInterfaceCastableImplementationForwarderAttribute : DynamicInterfaceCastableImplementationForwarderAttribute -{ - /// - /// The shared placeholder instance. - /// - public static PlaceholderDynamicInterfaceCastableImplementationForwarderAttribute Instance = new(); - - /// - public override bool TryGetImplementationType( - WindowsRuntimeObjectReference thisReference, - [NotNullWhen(true)] out WindowsRuntimeObjectReference? interfaceReference, - [NotNullWhen(true)] out Type? implementationType) - { - interfaceReference = null; - implementationType = null; - - return false; - } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMarshallingInfo.cs b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMarshallingInfo.cs index 479a8f864..c9f5e304f 100644 --- a/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMarshallingInfo.cs +++ b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMarshallingInfo.cs @@ -84,6 +84,7 @@ internal sealed class WindowsRuntimeMarshallingInfo /// For other generated associations (eg. generic type instantiations), this would also /// be the generated proxy type. This is because there would be no other way to link the /// additional metadata required for marshalling to the original types otherwise. + /// The same applies to custom-mapped types (e.g. fundamental types). /// /// /// @@ -94,6 +95,11 @@ internal sealed class WindowsRuntimeMarshallingInfo /// private volatile Type? _publicType; + /// + /// The reference type (a constructed type) for the current instance. + /// + private volatile Type? _referenceType; + /// /// The cached instance (possibly a placeholder). /// @@ -111,7 +117,23 @@ internal sealed class WindowsRuntimeMarshallingInfo /// This is only used for managed types that are marshalled to native. For RCWs (ie. for Windows /// Runtime projected types), the runtime class name would just be provided by the native object. /// - private string? _runtimeClassName; + private volatile string? _runtimeClassName; + + /// + /// The cached metadata type name for the type. + /// + /// + /// This is only used for marshalling, and it will only be available for some types (e.g. value types). + /// + private volatile string? _metadataTypeName; + + /// + /// A flag indicating whether the current type is a type defined in metadata (either projected or custom-mapped). + /// + /// + /// A value of -1 indicates a value that has not been computed yet. + /// + private volatile int _isMetadataType; /// /// Creates a new instance with the specified parameters. @@ -122,6 +144,20 @@ private WindowsRuntimeMarshallingInfo(Type metadataProviderType, Type? publicTyp { _metadataProviderType = metadataProviderType; _publicType = publicType; + _isMetadataType = -1; + } + + /// + /// Creates a new instance with the specified parameters. + /// + /// + /// + /// + private WindowsRuntimeMarshallingInfo(Type metadataProviderType, Type? publicType, bool isMetadataType) + { + _metadataProviderType = metadataProviderType; + _publicType = publicType; + _isMetadataType = isMetadataType ? 1 : 0; } /// @@ -153,6 +189,81 @@ Type InitializePublicType() } } + /// + /// Gets the reference type (a constructed type) for the current instance. + /// + public Type ReferenceType + { + get + { + [MethodImpl(MethodImplOptions.NoInlining)] + Type InitializeReferenceType() + { + // Try to get the attribute, which should always be present for value types + WindowsRuntimeReferenceTypeAttribute? referenceTypeAttribute = _metadataProviderType.GetCustomAttribute(inherit: false); + + // Analogous validation as for when retrieving the marshaller attribute + [DoesNotReturn] + [StackTraceHidden] + void ThrowNotSupportedException() + { + throw new NotSupportedException( + $"The metadata provider type '{_metadataProviderType}' does not have an associated reference type. " + + $"This code path should have never been reached. Please file an issue at https://github.com/microsoft/CsWinRT."); + } + + // We expect this to always be present for value types. If the attribute is 'null', it means that + // either a value type was missing it, or that 'ReferenceType' was accessed for an invalid public + // type (e.g. some Windows Runtime class type). In both cases, this is a bug, and we should throw. + if (referenceTypeAttribute is null) + { + ThrowNotSupportedException(); + } + + // Cache the reference type for later (no interlocked operations are needed, same as above) + return _referenceType ??= referenceTypeAttribute.ReferenceType; + } + + return _referenceType ?? InitializeReferenceType(); + } + } + + /// + /// Gets whether or not the managed type for the current instance is a Windows Runtime type (either projected or custom-mapped). + /// + public bool IsMetadataType + { + get + { + // This fallback will only ever be triggered for custom-mapped types (e.g. 'System.Guid'). + // We structure the code this way so this lookup on the proxy is only ever paid in those + // cases, and only if someone is actually trying to check the value of this property. + // In practice, this is only needed for 'TypeName' marshalling, which is exclusively a + // XAML scenario. So this code path should never be hit for any non-UI applications. + [MethodImpl(MethodImplOptions.NoInlining)] + bool InitializeIsMetadataType() + { + // We want to make sure that this code path is actually only triggered for proxy types, which + // are only for custom-mapped types. So '[WindowsRuntimeMetadata]' should not be defined here. + Debug.Assert(!_metadataProviderType.IsDefined(typeof(WindowsRuntimeMetadataAttribute), inherit: false)); + + bool isMetadataType = _metadataProviderType.IsDefined(typeof(WindowsRuntimeMappedMetadataAttribute), inherit: false); + + _isMetadataType = isMetadataType ? 1 : 0; + + return isMetadataType; + } + + // Convert the flag back to a boolean, or compute the deferred attribute lookup + return _isMetadataType switch + { + 0 => false, + 1 => true, + _ => InitializeIsMetadataType() + }; + } + } + /// /// Tries to get a instance for a given runtime class name. /// @@ -370,11 +481,11 @@ bool Load([NotNullWhen(true)] out WindowsRuntimeComWrappersMarshallerAttribute? { WindowsRuntimeComWrappersMarshallerAttribute? value = _metadataProviderType.GetCustomAttribute(inherit: false); - value ??= PlaceholderWindowsRuntimeComWrappersMarshallerAttribute.Instance; + value ??= WindowsRuntimeComWrappersMarshallerAttributePlaceholder.Instance; _comWrappersMarshaller = value; - if (value is not (null or PlaceholderWindowsRuntimeComWrappersMarshallerAttribute)) + if (value is not (null or WindowsRuntimeComWrappersMarshallerAttributePlaceholder)) { marshaller = value; @@ -391,7 +502,7 @@ bool Load([NotNullWhen(true)] out WindowsRuntimeComWrappersMarshallerAttribute? // We have a cached marshaller, so return it immediately if (value is not null) { - if (value is PlaceholderWindowsRuntimeComWrappersMarshallerAttribute) + if (value is WindowsRuntimeComWrappersMarshallerAttributePlaceholder) { marshaller = null; @@ -443,8 +554,34 @@ unsafe WindowsRuntimeVtableInfo InitializeVtableInfo() /// This method is only meant to be used on managed types passed to native. public string GetRuntimeClassName() { + if (!TryGetRuntimeClassName(out string? runtimeClassName)) + { + // Analogous validation as for when retrieving the marshaller attribute + [DoesNotReturn] + [StackTraceHidden] + void ThrowNotSupportedException() + { + throw new NotSupportedException( + $"The metadata provider type '{_metadataProviderType}' does not have any runtime class name info. " + + $"This should never be the case. Please file an issue at https://github.com/microsoft/CsWinRT."); + } + + ThrowNotSupportedException(); + } + + return runtimeClassName; + } + + /// + /// Tries to get the runtime class name for the public type associated with the current metadata provider type. + /// + /// The resulting runtime class name, if available. + /// Whether was retrieved successfully. + public bool TryGetRuntimeClassName([NotNullWhen(true)] out string? runtimeClassName) + { + // Initializes the runtime class name, if present [MethodImpl(MethodImplOptions.NoInlining)] - string InitializeRuntimeClassName() + bool Load([NotNullWhen(true)] out string? runtimeClassName) { WindowsRuntimeClassNameAttribute? runtimeClassNameAttribute = _metadataProviderType.GetCustomAttribute(inherit: false) @@ -452,23 +589,112 @@ string InitializeRuntimeClassName() if (runtimeClassNameAttribute is null) { - // Analogous validation as for when retrieving the marshaller attribute - [DoesNotReturn] - [StackTraceHidden] - void ThrowNotSupportedException() - { - throw new NotSupportedException( - $"The metadata provider type '{_metadataProviderType}' does not have any runtime class name info. " + - $"This should never be the case. Please file an issue at https://github.com/microsoft/CsWinRT."); - } + _runtimeClassName ??= ""; + + runtimeClassName = null; + + return false; + } + + _runtimeClassName = runtimeClassNameAttribute.RuntimeClassName; + + runtimeClassName = runtimeClassNameAttribute.RuntimeClassName; + + return true; + } + + string? value = _runtimeClassName; + + // We have a cached runtime class name, so return it immediately + if (value is not null) + { + if (value is "") + { + runtimeClassName = null; + + return false; + } + + runtimeClassName = value; + + return true; + } + + return Load(out runtimeClassName); + } + + /// + /// Gets the metadata type name for the public type associated with the current metadata provider type. + /// + /// The resulting metadata type name. + /// Thrown if no metadata type name could be resolved. + public string GetMetadataTypeName() + { + if (!TryGetMetadataTypeName(out string? metadataTypeName)) + { + // Analogous validation as for when retrieving the marshaller attribute + [DoesNotReturn] + [StackTraceHidden] + void ThrowNotSupportedException() + { + throw new NotSupportedException( + $"The metadata provider type '{_metadataProviderType}' does not have any metadata type name info. " + + $"This path should never be reached. Please file an issue at https://github.com/microsoft/CsWinRT."); + } + + ThrowNotSupportedException(); + } + + return metadataTypeName; + } + + /// + /// Tries to get the metadata type name for the public type associated with the current metadata provider type. + /// + /// The resulting metadata type name, if available. + /// Whether was retrieved successfully. + public bool TryGetMetadataTypeName([NotNullWhen(true)] out string? metadataTypeName) + { + // Initializes the metadata type name, if present + [MethodImpl(MethodImplOptions.NoInlining)] + bool Load([NotNullWhen(true)] out string? metadataTypeName) + { + WindowsRuntimeMetadataTypeNameAttribute? metadataTypeNameAttribute = _metadataProviderType.GetCustomAttribute(inherit: false); + + if (metadataTypeNameAttribute is null) + { + _metadataTypeName ??= ""; - ThrowNotSupportedException(); + metadataTypeName = null; + + return false; } - return _runtimeClassName ??= runtimeClassNameAttribute.RuntimeClassName; + _metadataTypeName = metadataTypeNameAttribute.MetadataTypeName; + + metadataTypeName = metadataTypeNameAttribute.MetadataTypeName; + + return true; } - return _runtimeClassName ?? InitializeRuntimeClassName(); + string? value = _metadataTypeName; + + // We have a cached metadata type name, so return it immediately + if (value is not null) + { + if (value is "") + { + metadataTypeName = null; + + return false; + } + + metadataTypeName = value; + + return true; + } + + return Load(out metadataTypeName); } /// @@ -481,24 +707,26 @@ private static WindowsRuntimeMarshallingInfo CreateMarshallingInfo(Type metadata // If '[WindowsRuntimeMetadata]' is defined, this is a projected type, so it's the public type too. // Otherwise, we don't know what the public type is at this point. We could look it up now, but // since we don't need that information right away, we can delay this to later to reduce the - // overhead at startup. That value is only needed eg. when associating native memory for vtables. + // overhead at startup. That value is only needed e.g. when associating native memory for vtables. return metadataProviderType.IsDefined(typeof(WindowsRuntimeMetadataAttribute), inherit: false) - ? new(metadataProviderType, metadataProviderType) + ? new(metadataProviderType, metadataProviderType, isMetadataType: true) : new(metadataProviderType, publicType: null); } /// /// Creates a instance associated with a given managed type, if possible. /// - /// The managed type to create an instance for, if possible.. + /// The managed type to create an instance for, if possible. /// The resulting instance, if created successfully. private static WindowsRuntimeMarshallingInfo? GetMetadataProviderType(Type managedType) { + bool isMetadataType = managedType.IsDefined(typeof(WindowsRuntimeMetadataAttribute), inherit: false); + // Same as above: if the type is a projected type, then it is also used as the metadata source. // We need to special-case generic types, as the marshalling code for them is also on proxies. - if (managedType.IsDefined(typeof(WindowsRuntimeMetadataAttribute), inherit: false) && !managedType.IsGenericType) + if (isMetadataType && !managedType.IsGenericType) { - return new(managedType, publicType: managedType); + return new(managedType, publicType: managedType, isMetadataType: true); } // Check if we have a mapped proxy type for this managed type. If we do, that type @@ -506,43 +734,16 @@ private static WindowsRuntimeMarshallingInfo CreateMarshallingInfo(Type metadata // type. In this case, we don't need to query for '[WindowsRuntimeMappedType]'. if (ProxyTypeMapping.TryGetValue(managedType, out Type? proxyType)) { - return new(proxyType, publicType: managedType); + // If the managed type is a metadata type, we have all the information we need. + // However, if the attribute wasn't present, we cannot be certain that the type + // is not in fact a metadata type, as it could also be a custom-mapped type. In + // that case, we defer this check to later, with a lookup on the proxy type. + return isMetadataType + ? new(proxyType, publicType: managedType, isMetadataType) + : new(proxyType, publicType: managedType); } // We don't have a metadata provider for the type (we'll just marshal it as a generic 'IInspectable') return null; } -} - -/// -/// A placeholder type. -/// -file sealed unsafe class PlaceholderWindowsRuntimeComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute -{ - /// - /// The shared placeholder instance. - /// - public static PlaceholderWindowsRuntimeComWrappersMarshallerAttribute Instance = new(); - - /// - public override void* GetOrCreateComInterfaceForObject(object value) - { - return null; - } - - /// - public override ComWrappers.ComInterfaceEntry* ComputeVtables(out int count) - { - count = 0; - - return null; - } - - /// - public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) - { - wrapperFlags = CreatedWrapperFlags.None; - - return null!; - } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMetadataInfo.cs b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMetadataInfo.cs new file mode 100644 index 000000000..788bc6213 --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMetadataInfo.cs @@ -0,0 +1,215 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +#pragma warning disable IDE0008 + +namespace WindowsRuntime.InteropServices; + +/// +/// A type providing cached metadata information on Windows Runtime types. +/// +internal sealed class WindowsRuntimeMetadataInfo +{ + /// + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect external types to only be preserved if used in runtime casts.")] + private static readonly IReadOnlyDictionary ExternalTypeMapping = TypeMapping.GetOrCreateExternalTypeMapping(); + + /// + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect only proxy types for constructed types to be preserved.")] + private static readonly IReadOnlyDictionary ProxyTypeMapping = TypeMapping.GetOrCreateProxyTypeMapping(); + + /// + private static readonly ConcurrentDictionary TypeNameToMappedTypeDictionary = []; + + /// + /// The table of metadata info for all types that require special handling. + /// + /// + /// This will only have non values for types needing special metadata handling. + /// + private static readonly ConditionalWeakTable TypeToMetadataInfoTable = []; + + /// + /// Cached creation factory for . + /// + private static readonly Func CreateMetadataInfoCallback = new(CreateMetadataInfo); + + /// + /// Cached creation factory for . + /// + private static readonly Func GetMetadataProviderTypeCallback = new(GetMetadataProviderType); + + /// + /// The metadata provider type associated with the current instance (ie. the mapped type to use to resolve attributes). + /// + /// + /// Here's some examples of how this type would relate to the associated metadata type in different scenarios: + /// + /// For a Windows Runtime projected type, this would be the same as the metadata type. + /// For custom-mapped types, this would be some proxy type with the right attributes on it. + /// + /// + private readonly Type _metadataProviderType; + + /// + private volatile Type? _publicType; + + /// + /// The cached metadata type name for the type. + /// + private volatile string? _metadataTypeName; + + /// + /// Creates a new instance with the specified parameters. + /// + /// + /// + private WindowsRuntimeMetadataInfo(Type metadataProviderType, Type? publicType) + { + _metadataProviderType = metadataProviderType; + _publicType = publicType; + } + + /// + public Type PublicType + { + get + { + // Same implementation as in 'WindowsRuntimeMarshallingInfo.PublicType', see notes there + [MethodImpl(MethodImplOptions.NoInlining)] + Type InitializePublicType() + { + WindowsRuntimeMappedTypeAttribute mappedTypeAttribute = _metadataProviderType.GetCustomAttribute(inherit: false)!; + + Debug.Assert(mappedTypeAttribute is not null); + + return _publicType ??= mappedTypeAttribute.PublicType; + } + + return _publicType ?? InitializePublicType(); + } + } + + /// + /// Tries to get a instance for a given metadata type name. + /// + /// The input metadata type name to use for lookups. + /// The resulting instance, if found. + /// Whether was retrieved successfully. + public static bool TryGetInfo(ReadOnlySpan metadataTypeName, [NotNullWhen(true)] out WindowsRuntimeMetadataInfo? info) + { + // Tries to get the external type for the input metadata type name + static Type? TryGetExternalType(ReadOnlySpan runtimeClassName) + { + var alternate = TypeNameToMappedTypeDictionary.GetAlternateLookup>(); + + // Check if we already have a cached result (it might be 'null') + if (alternate.TryGetValue(runtimeClassName, out Type? externalType)) + { + return externalType; + } + + // Try to get the external type (which might not be present, if the entry has been removed) + _ = ExternalTypeMapping.TryGetValue(runtimeClassName.ToString(), out externalType); + + // Try to add the cached value to the table + _ = alternate.TryAdd(runtimeClassName, externalType); + + // Always return the external type (see notes in 'WindowsRuntimeMarshallingInfo') + return externalType; + } + + Type? externalType = TryGetExternalType(metadataTypeName); + + // We found a mapped external type, return its associated marshalling info + if (externalType is not null) + { + info = TypeToMetadataInfoTable.GetOrAdd(externalType, CreateMetadataInfoCallback)!; + + return true; + } + + info = null; + + return false; + } + + /// + /// Tries to get a instance for a given managed type. + /// + /// The input managed type to use for lookups. + /// The resulting instance, if found. + /// Whether was retrieved successfully. + public static bool TryGetInfo(Type managedType, [NotNullWhen(true)] out WindowsRuntimeMetadataInfo? info) + { + WindowsRuntimeMetadataInfo? result = TypeToMetadataInfoTable.GetOrAdd(managedType, GetMetadataProviderTypeCallback); + + info = result; + + return result is not null; + } + + /// + /// Gets the metadata type name for the public type associated with the current metadata provider type. + /// + /// The resulting metadata type name. + public string GetMetadataTypeName() + { + [MethodImpl(MethodImplOptions.NoInlining)] + string InitializeMetadataTypeName() + { + WindowsRuntimeMetadataTypeNameAttribute? metadataTypeNameAttribute = + _metadataProviderType.GetCustomAttribute(inherit: false); + + string metadataTypeName = metadataTypeNameAttribute?.MetadataTypeName ?? _metadataProviderType.FullName!; + + return _metadataTypeName ??= metadataTypeName; + } + + return _metadataTypeName ?? InitializeMetadataTypeName(); + } + + /// + /// Creates a instance for a specified metadata provider type. + /// + /// The metadata provider type to wrap. + /// The resulting instance. + private static WindowsRuntimeMetadataInfo CreateMetadataInfo(Type metadataProviderType) + { + return metadataProviderType.IsDefined(typeof(WindowsRuntimeMetadataAttribute), inherit: false) + ? new(metadataProviderType, metadataProviderType) + : new(metadataProviderType, publicType: null); + } + + /// + /// Creates a instance associated with a given managed type, if possible. + /// + /// The managed type to create an instance for, if possible. + /// The resulting instance, if created successfully. + private static WindowsRuntimeMetadataInfo? GetMetadataProviderType(Type managedType) + { + // Same as above: if the type is a projected type, then it is also used as the metadata source + if (managedType.IsDefined(typeof(WindowsRuntimeMetadataAttribute), inherit: false) && !managedType.IsGenericType) + { + return new(managedType, managedType); + } + + // If we have a proxy type, then that will be the metadata provider + if (ProxyTypeMapping.TryGetValue(managedType, out Type? proxyType)) + { + return new(proxyType, managedType); + } + + // We don't have a metadata provider for the type + return null; + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs b/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs index aa5d3c3e1..96d6edb41 100644 --- a/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs +++ b/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs @@ -3,6 +3,7 @@ using System; using System.Collections; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using WindowsRuntime.InteropServices.Marshalling; @@ -117,11 +118,9 @@ public nint GetOrCreateComInterfaceForObject(object instance) } else { - // Special case 'Exception', see notes in 'ComputeVtables' below for more details. Repeating this here - // allows us to still skip the repeated lookup, as we already know we won't find a matching key pair. - MarshallingInfo = instance is Exception - ? WindowsRuntimeMarshallingInfo.GetInfo(typeof(Exception)) - : WindowsRuntimeMarshallingInfo.GetInfo(typeof(object)); + // If we couldn't retrieve the marshalling info, get the one to marshal anonymous objects. + // E.g. this would be the case when marshalling a custom exception type, or some 'Type'. + MarshallingInfo = GetAnonymousInspectableMarshallingInfo(instance); thisPtr = (void*)GetOrCreateComInterfaceForObject(instance, CreateComInterfaceFlags.TrackerSupport); } @@ -222,11 +221,7 @@ public object GetOrCreateObjectForComInstanceUnsafe( // If we already have one available passed by callers up the stack, we can skip the lookup and just use it. if (marshallingInfo is null && !WindowsRuntimeMarshallingInfo.TryGetInfo(obj.GetType(), out marshallingInfo)) { - // Special case for exception types, which won't have their own type map entry, but should all map to the - // same marshalling info for 'Exception'. Since we have an instance here, we can just check directly. - marshallingInfo = obj is Exception - ? WindowsRuntimeMarshallingInfo.GetInfo(typeof(Exception)) - : WindowsRuntimeMarshallingInfo.GetInfo(typeof(object)); + marshallingInfo = GetAnonymousInspectableMarshallingInfo(obj); } // Get the vtable from the current marshalling info (it will get cached in that instance) @@ -345,4 +340,34 @@ protected override void ReleaseObjects(IEnumerable objects) } } } + + /// + /// Gets the value to marshal an anonymous (managed) object. + /// + /// The managed object to expose outside the .NET runtime. + /// The value to use to marshal . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static WindowsRuntimeMarshallingInfo GetAnonymousInspectableMarshallingInfo(object instance) + { + // Special case for (derived) exception types, which won't have their own type map entry, but should all map + // to the same marshalling info for 'Exception'. Since we have an instance here, we can just check directly. + // Note that custom exception types that might implement additional interfaces will still just be marshalled + // as any other exception type (i.e. as just 'HResult'). This is intended and by design. + if (instance is Exception) + { + return WindowsRuntimeMarshallingInfo.GetInfo(typeof(Exception)); + } + + // Special case for 'Type' instances too. This is needed even without considering custom user-defined types + // (which shouldn't really be common anyway), because 'Type' itself is just a base type and not instantiated. + // That is, when e.g. doing 'typeof(Foo)', the actual object is some 'RuntimeType' object itself (non public). + if (instance is Type) + { + return WindowsRuntimeMarshallingInfo.GetInfo(typeof(Type)); + } + + // For all other cases, we fallback to the marshalling info for 'object'. This is the + // shared marshalling mode for all unknown objects, ie. just an opaque 'IInspectable'. + return WindowsRuntimeMarshallingInfo.GetInfo(typeof(object)); + } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/Windows.Foundation/Collections/CollectionChange.cs b/src/WinRT.Runtime2/Windows.Foundation/Collections/CollectionChange.cs index 23f64d690..ad9076508 100644 --- a/src/WinRT.Runtime2/Windows.Foundation/Collections/CollectionChange.cs +++ b/src/WinRT.Runtime2/Windows.Foundation/Collections/CollectionChange.cs @@ -19,6 +19,8 @@ namespace Windows.Foundation.Collections; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.Collections.CollectionChange")] +[WindowsRuntimeReferenceType(typeof(CollectionChange?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.Collections.CollectionChangeComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.Foundation/Point.cs b/src/WinRT.Runtime2/Windows.Foundation/Point.cs index d46441d08..8b14cdd48 100644 --- a/src/WinRT.Runtime2/Windows.Foundation/Point.cs +++ b/src/WinRT.Runtime2/Windows.Foundation/Point.cs @@ -19,6 +19,7 @@ namespace Windows.Foundation; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeReferenceType(typeof(Point?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.PointComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.Foundation/Rect.cs b/src/WinRT.Runtime2/Windows.Foundation/Rect.cs index 68c339bd2..eaed310d5 100644 --- a/src/WinRT.Runtime2/Windows.Foundation/Rect.cs +++ b/src/WinRT.Runtime2/Windows.Foundation/Rect.cs @@ -21,6 +21,7 @@ namespace Windows.Foundation; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeReferenceType(typeof(Rect?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.RectComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.Foundation/Size.cs b/src/WinRT.Runtime2/Windows.Foundation/Size.cs index 94534d0d1..f3519caf5 100644 --- a/src/WinRT.Runtime2/Windows.Foundation/Size.cs +++ b/src/WinRT.Runtime2/Windows.Foundation/Size.cs @@ -18,6 +18,7 @@ namespace Windows.Foundation; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference")] +[WindowsRuntimeReferenceType(typeof(Size?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.SizeComWrappersMarshaller] diff --git a/src/cswinrt.slnx b/src/cswinrt.slnx index 7db15b0a3..24c751453 100644 --- a/src/cswinrt.slnx +++ b/src/cswinrt.slnx @@ -323,6 +323,12 @@ + + + + + + diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index 13ff88e44..c54899e7b 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -4641,17 +4641,47 @@ R"(file static class %InterfaceEntriesImpl )", name, name, bind(type), name, bind(type), name); } + + void write_pragma_restore_IL2026(writer& w) + { + w.write( +R"( +#pragma warning restore IL2026 +)"); + } + + void write_pragma_disable_IL2026(writer& w) + { + w.write( +R"( +#pragma warning disable IL2026 +)"); + } + + void write_winrt_windowsmetadata_typemapgroup_assembly_attribute(writer& w, TypeDef const& type) + { + auto projection_name = w.write_temp("%", bind(type, typedef_name_type::NonProjected, true)); + w.write( +R"( +[assembly: TypeMap( + value: "%", + target: typeof(%), + trimTarget: typeof(%))] +)", + projection_name, + projection_name, + projection_name); + } + void write_winrt_comwrappers_typemapgroup_assembly_attribute(writer& w, TypeDef const& type, bool is_value_type) { auto projection_name = w.write_temp("%", bind(type, typedef_name_type::NonProjected, true)); w.write( -R"(#pragma warning disable IL2026 +R"( [assembly: TypeMap( value: "%", target: typeof(%), trimTarget: typeof(%))] -#pragma warning restore IL2026 - )", bind([&](writer& w) { if (is_value_type) @@ -4691,6 +4721,11 @@ R"(#pragma warning disable IL2026 bind(type, typedef_name_type::ABI, true)); } + void write_winrt_reference_type_attribute(writer& w, TypeDef const& type) + { + w.write("[WindowsRuntimeReferenceType(typeof(%?))]\n", type.TypeName()); + } + void write_winrt_metadata_attribute(writer& w, TypeDef const& type) { std::filesystem::path db_path(type.get_database().path()); @@ -9150,13 +9185,14 @@ internal unsafe struct %Vftbl w.write( R"( -%%%%% enum % : % +%%%%%% enum % : % { )", is_flags_enum(type) ? "[FlagsAttribute]\n" : "", bind(type), bind(type, true), bind(type), + bind(type), (settings.internal) ? "internal" : "public", bind(type, typedef_name_type::Projected, false), enum_underlying_type); { @@ -9215,10 +9251,11 @@ R"( } // struct - w.write("%%%public% struct %: IEquatable<%>\n{\n", + w.write("%%%%public% struct %: IEquatable<%>\n{\n", bind(type), bind(type), bind(type), + bind(type), has_addition_to_type(type) ? " partial" : "", type.TypeName(), type.TypeName()); diff --git a/src/cswinrt/helpers.h b/src/cswinrt/helpers.h index 458528b63..57e67518f 100644 --- a/src/cswinrt/helpers.h +++ b/src/cswinrt/helpers.h @@ -714,8 +714,8 @@ namespace cswinrt { "IGridLengthHelperStatics" }, { "IThicknessHelper" }, { "IThicknessHelperStatics" }, - { "ThicknessHelper" }, { "IXamlServiceProvider", "System", "IServiceProvider" }, + { "ThicknessHelper" }, } }, { "Microsoft.UI.Xaml.Controls.Primitives", @@ -866,8 +866,8 @@ namespace cswinrt { "IGridLengthHelperStatics" }, { "IThicknessHelper" }, { "IThicknessHelperStatics" }, - { "ThicknessHelper" }, { "IXamlServiceProvider", "System", "IServiceProvider" }, + { "ThicknessHelper" }, } }, { "Windows.UI.Xaml.Controls.Primitives", diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp index ceb34c7d9..3638304ae 100644 --- a/src/cswinrt/main.cpp +++ b/src/cswinrt/main.cpp @@ -263,6 +263,7 @@ Where is one or more of: continue; } } + auto guard{ w.push_generic_params(type.GenericParam()) }; auto guard1{ helperWriter.push_generic_params(type.GenericParam()) }; @@ -273,23 +274,37 @@ Where is one or more of: if (!is_static(type) && !is_attribute_type(type)) { + write_pragma_disable_IL2026(w); write_winrt_comwrappers_typemapgroup_assembly_attribute(w, type, false); + write_pragma_restore_IL2026(w); } break; case category::delegate_type: + write_pragma_disable_IL2026(w); write_winrt_comwrappers_typemapgroup_assembly_attribute(w, type, true); + write_winrt_windowsmetadata_typemapgroup_assembly_attribute(w, type); + write_pragma_restore_IL2026(w); break; case category::enum_type: + write_pragma_disable_IL2026(w); write_winrt_comwrappers_typemapgroup_assembly_attribute(w, type, true); + write_winrt_windowsmetadata_typemapgroup_assembly_attribute(w, type); + write_pragma_restore_IL2026(w); break; case category::interface_type: + write_pragma_disable_IL2026(w); write_winrt_idic_typemapgroup_assembly_attribute(w, type); + write_winrt_windowsmetadata_typemapgroup_assembly_attribute(w, type); + write_pragma_restore_IL2026(w); break; case category::struct_type: // Similarly for API contracts, we don't expect them to be passed across the ABI. if (!is_api_contract_type(type)) { + write_pragma_disable_IL2026(w); write_winrt_comwrappers_typemapgroup_assembly_attribute(w, type, true); + write_winrt_windowsmetadata_typemapgroup_assembly_attribute(w, type); + write_pragma_restore_IL2026(w); } break; }