diff --git a/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs b/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs index f64554ec1..73ea894b4 100644 --- a/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs +++ b/src/Authoring/WinRT.SourceGenerator2/TypeMapAssemblyTargetGenerator.Execute.cs @@ -104,6 +104,7 @@ 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}")] """); } @@ -130,6 +131,11 @@ 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")] diff --git a/src/Projections/Test/Test.csproj b/src/Projections/Test/Test.csproj index d15aa7b43..98c13569d 100644 --- a/src/Projections/Test/Test.csproj +++ b/src/Projections/Test/Test.csproj @@ -20,6 +20,7 @@ TestComponentCSharp.AnotherAssembly; + TestComponentCSharp.TestTypeTrimmed; TestComponent; diff --git a/src/Tests/FunctionalTests/TypeMarshaling/Program.cs b/src/Tests/FunctionalTests/TypeMarshaling/Program.cs new file mode 100644 index 000000000..11157585c --- /dev/null +++ b/src/Tests/FunctionalTests/TypeMarshaling/Program.cs @@ -0,0 +1,322 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Windows.Input; +using TestComponent; +using TestComponentCSharp; +using Windows.Foundation; +using WindowsRuntime.InteropServices; + +int failure; + +TypeCase[] TestCases = +[ + // -------------------- + // Projected WinRT Types (existing e2e cases) + // -------------------- + new(typeof(TestComponentCSharp.Class), "TestComponentCSharp.Class", "Metadata", 101), + + // -------------------- + // Custom Type (existing e2e case) + // -------------------- + new(typeof(TestType), "TestType, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Custom", 150), + + // -------------------- + // Mapped System.* Types Primitive Types + // -------------------- + new(typeof(bool), "Boolean", "Primitive", 200), + new(typeof(byte), "UInt8", "Primitive", 201), + new(typeof(char), "Char16", "Primitive", 202), + new(typeof(double), "Double", "Primitive", 203), + new(typeof(short), "Int16", "Primitive", 204), + new(typeof(int), "Int32", "Primitive", 205), + new(typeof(long), "Int64", "Primitive", 206), + new(typeof(float), "Single", "Primitive", 207), + new(typeof(ushort), "UInt16", "Primitive", 208), + new(typeof(uint), "UInt32", "Primitive", 209), + new(typeof(ulong), "UInt64", "Primitive", 210), + + // -------------------- + // Mapped System.* Types Metadata Types + // -------------------- + new(typeof(DateTimeOffset), "Windows.Foundation.DateTime", "Metadata", 250), + new(typeof(EventHandler), "Windows.Foundation.EventHandler`1", "Metadata", 251), + new(typeof(Exception), "Windows.Foundation.HResult", "Metadata", 252), + new(typeof(Guid), "Guid", "Metadata", 253), + new(typeof(IDisposable), "Windows.Foundation.IClosable", "Metadata", 254), + new(typeof(IServiceProvider), "Microsoft.UI.Xaml.IXamlServiceProvider", "Metadata", 255), + new(typeof(object), "Object", "Metadata", 256), + new(typeof(string), "String", "Metadata", 257), + new(typeof(TimeSpan), "Windows.Foundation.TimeSpan", "Metadata", 258), + new(typeof(Type), "Windows.UI.Xaml.Interop.TypeName", "Metadata", 259), + new(typeof(Uri), "Windows.Foundation.Uri", "Metadata", 260), + new(typeof(ICommand), "Microsoft.UI.Xaml.Input.ICommand", "Metadata", 261), + + // -------------------- + // Mapped System.Collections.* Types + // -------------------- + new(typeof(IEnumerable), "Microsoft.UI.Xaml.Interop.IBindableIterable", "Metadata", 300), + new(typeof(IEnumerator), "Microsoft.UI.Xaml.Interop.IBindableIterator", "Metadata", 301), + new(typeof(IList), "Microsoft.UI.Xaml.Interop.IBindableVector", "Metadata", 302), + new(typeof(IReadOnlyList), "Windows.Foundation.Collections.IVectorView`1", "Metadata", 303), + + // -------------------- + // Mapped System.Collections.Specialized* Types + // -------------------- + new(typeof(INotifyCollectionChanged), "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged", "Metadata", 350), + new(typeof(NotifyCollectionChangedEventArgs), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", "Metadata", 351), + new(typeof(NotifyCollectionChangedEventHandler),"Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler","Metadata", 352), + + // -------------------- + // Mapped System.ComponentModel.* Types + // -------------------- + new(typeof(DataErrorsChangedEventArgs), "Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs", "Metadata", 400), + new(typeof(INotifyDataErrorInfo), "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo", "Metadata", 401), + new(typeof(INotifyPropertyChanged), "Microsoft.UI.Xaml.Data.INotifyPropertyChanged", "Metadata", 402), + new(typeof(PropertyChangedEventArgs), "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs", "Metadata", 403), + new(typeof(PropertyChangedEventHandler),"Microsoft.UI.Xaml.Data.PropertyChangedEventHandler","Metadata", 404), + + // -------------------- + // Mapped System.Numerics.* Types + // -------------------- + new(typeof(Matrix3x2), "Windows.Foundation.Numerics.Matrix3x2", "Metadata", 450), + new(typeof(Matrix4x4), "Windows.Foundation.Numerics.Matrix4x4", "Metadata", 451), + new(typeof(Plane), "Windows.Foundation.Numerics.Plane", "Metadata", 452), + new(typeof(Quaternion), "Windows.Foundation.Numerics.Quaternion", "Metadata", 453), + new(typeof(Vector2), "Windows.Foundation.Numerics.Vector2", "Metadata", 454), + new(typeof(Vector3), "Windows.Foundation.Numerics.Vector3", "Metadata", 455), + new(typeof(Vector4), "Windows.Foundation.Numerics.Vector4", "Metadata", 456), + + // -------------------- + // Mapped Windows.Foundation.* Types + // -------------------- + new(typeof(AsyncActionCompletedHandler), "Windows.Foundation.AsyncActionCompletedHandler", "Metadata", 500), + new(typeof(IAsyncAction), "Windows.Foundation.IAsyncAction", "Metadata", 501), + new(typeof(IAsyncInfo), "Windows.Foundation.IAsyncInfo", "Metadata", 502), + new(typeof(Point), "Windows.Foundation.Point", "Metadata", 503), + new(typeof(Rect), "Windows.Foundation.Rect", "Metadata", 504), + new(typeof(Size), "Windows.Foundation.Size", "Metadata", 505), + new(typeof(IStringable), "Windows.Foundation.IStringable", "Metadata", 506), + + // -------------------- + // Mapped Windows.Foundation.Collections.* Types + // -------------------- + new(typeof(Windows.Foundation.Collections.CollectionChange), "Windows.Foundation.Collections.CollectionChange", "Metadata", 550), + new(typeof(Windows.Foundation.Collections.IVectorChangedEventArgs),"Windows.Foundation.Collections.IVectorChangedEventArgs", "Metadata", 551), + + // -------------------- + // Mapped WindowsRuntime.InteropServices.* Types + // -------------------- + new(typeof(EventRegistrationToken), "WindowsRuntime.InteropServices.EventRegistrationToken", "Metadata", 600), + + // -------------------- + // Projected WinRT Types + // -------------------- + new(typeof(TestComponent.Class), "TestComponent.Class", "Metadata", 650), + new(typeof(TestComponent.Nested), "TestComponent.Nested", "Metadata", 651), + new(typeof(TestComponent.IRequiredOne), "TestComponent.IRequiredOne", "Metadata", 652), + new(typeof(TestComponent.Param6Handler), "TestComponent.Param6Handler", "Metadata", 653), + new(typeof(TestComponentCSharp.Class), "TestComponentCSharp.Class", "Metadata", 654), + new(typeof(TestComponentCSharp.ComposedBlittableStruct),"TestComponentCSharp.ComposedBlittableStruct","Metadata", 655), + new(typeof(TestComponentCSharp.IArtist), "TestComponentCSharp.IArtist", "Metadata", 656), + new(typeof(TestComponentCSharp.EnumValue), "TestComponentCSharp.EnumValue", "Metadata", 657), + new(typeof(TestComponentCSharp.EventHandler0), "TestComponentCSharp.EventHandler0", "Metadata", 658), + + // -------------------- + // Nullable Types + // -------------------- + new(typeof(long?), "Windows.Foundation.IReference`1", "Metadata", 700), + new(typeof(Point?), "Windows.Foundation.IReference`1", "Metadata", 701), + new(typeof(Vector3?), "Windows.Foundation.IReference`1", "Metadata", 702), + new(typeof(Guid?), "Windows.Foundation.IReference`1", "Metadata", 703), + new(typeof(IList), "Windows.Foundation.Collections.IVector`1>", "Metadata", 704), + new(typeof(TestComponentCSharp.EnumValue?), "Windows.Foundation.IReference`1", "Metadata", 705), + new(typeof(TestComponentCSharp.BlittableStruct?), "Windows.Foundation.IReference`1", "Metadata", 706), + new(typeof(int?[]), "Windows.Foundation.IReferenceArray`1>", "Metadata", 707), + + // -------------------- + // Generic Types + // -------------------- + new(typeof(IList), "Windows.Foundation.Collections.IVector`1", "Metadata", 750), + new(typeof(IList),"Windows.Foundation.Collections.IVector`1", "Metadata", 751), + new(typeof(IList), "Windows.Foundation.Collections.IVector`1", "Metadata", 752), + new(typeof(IEnumerator),"Windows.Foundation.Collections.IIterator`1", "Metadata", 753), + new(typeof(IEnumerable),"Windows.Foundation.Collections.IIterable`1", "Metadata", 754), + new(typeof(EventHandler),"Windows.Foundation.EventHandler`1", "Metadata", 755), + new(typeof(KeyValuePair),"Windows.Foundation.Collections.IKeyValuePair`2", "Metadata", 756), + new(typeof(KeyValuePair), "Windows.Foundation.Collections.IKeyValuePair`2", "Metadata", 757), + new(typeof(KeyValuePair),"Windows.Foundation.Collections.IKeyValuePair`2", "Metadata", 758), + + // -------------------- + // Nested Generics + // -------------------- + new(typeof(EventHandler>), "Windows.Foundation.EventHandler`1>", "Metadata", 800), + new(typeof(EventHandler>), "Windows.Foundation.EventHandler`1>", "Metadata", 801), + new(typeof(EventHandler>), "Windows.Foundation.EventHandler`1>", "Metadata", 802), + new(typeof(IList>), "Windows.Foundation.Collections.IVector`1>", "Metadata", 803), + new(typeof(IEnumerator>), "Windows.Foundation.Collections.IIterator`1>", "Metadata", 804), + new(typeof(IEnumerable>), "Windows.Foundation.Collections.IIterable`1>", "Metadata", 805), + + // -------------------- + // Custom Types + // -------------------- + new(typeof(TestCSharp), "TestCSharp, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Custom", 850), + + new(typeof(IList), + "System.Collections.Generic.IList`1[[TestCSharp, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 851), + + new(typeof(ITestCSharp), + "ITestCSharp`1[[System.Double, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Custom", + 852), + + new(typeof(KeyValuePair), + "System.Collections.Generic.KeyValuePair`2[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[TestCSharp, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 853), + + new(typeof(EventHandler>), + "System.EventHandler`1[[System.Collections.Generic.IList`1[[TestCSharp, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 854), + + new(typeof(EventHandler), + "System.EventHandler`1[[TestCSharp, TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 855), + + new(typeof(DelegateTestCSharp), + "DelegateTestCSharp`1[[System.Guid, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], TypeMarshaling, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", + "Custom", + 856), + + new(typeof(WeakReference), + "System.WeakReference`1[[TestComponent.Class, WinRT.Projection, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 857), + + new(typeof(KeyValuePair>), + "System.Collections.Generic.KeyValuePair`2[[System.Int32, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.WeakReference`1[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 858), + + new(typeof(ICollection), + "System.Collections.Generic.ICollection`1[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 859), + + new(typeof(KeyValuePair?), + "System.Nullable`1[[System.Collections.Generic.KeyValuePair`2[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", + "Custom", + 860), + + // -------------------- + // Arrays + // -------------------- + new(typeof(object[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 950), + new(typeof(long[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 951), + new(typeof(TestComponentCSharp.Class[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 952), + new(typeof(TestComponentCSharp.ComposedBlittableStruct[]), + "Windows.Foundation.IReferenceArray`1", + "Metadata", + 953), + + new(typeof(TestComponentCSharp.IArtist[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 954), + new(typeof(TestComponentCSharp.EnumValue[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 955), + new(typeof(TestComponentCSharp.EventHandler0[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 956), + new(typeof(Point[]), "Windows.Foundation.IReferenceArray`1", "Metadata", 957), + new(typeof(IList[]), "Windows.Foundation.IReferenceArray`1>", "Metadata", 958), + new(typeof(IList[]), + "Windows.Foundation.IReferenceArray`1>>", + "Metadata", + 959), + + new(typeof(KeyValuePair[]), + "Windows.Foundation.IReferenceArray`1>", + "Metadata", + 960), + + // -------------------- + // Others + // -------------------- + new(typeof(NotifyCollectionChangedAction), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction", "Metadata", 1000), + new(typeof(NotifyCollectionChangedAction?), "Windows.Foundation.IReference`1", "Metadata", 1001), +]; + +// Convert to Managed Trimmed Metadata NoMetadataTypeInfo Test Case +// Goes into NoMetadataTypeInfo codepath for Type.cs ConvertToManaged +// Do not reference TestComponentCSharp::TestType1 in managed because it needs to be trimmed to test the Metadata TypeKind scenario +if ((failure = CheckTrimmed("TestComponentCSharp.TestTypeTrimmed Metadata", 101)) != 0) +{ + return failure; +} + +if ((failure = RunCases(TestCases)) != 0) +{ + return failure; +} + +return 100; + +static int RunCases(ReadOnlySpan cases) +{ + for (int i = 0; i < cases.Length; i++) + { + TypeCase c = cases[i]; + string expected = $"{c.Name} {c.Kind}"; + + int failure = CheckType(c.Type, expected, c.ErrorCode); + if (failure != 0) + { + return failure; + } + } + + return 0; +} + +static int CheckTrimmed(string expected, int errorCode) +{ + TestType testTypeClass = new(); + return FailIfNotEqual(new SetTypeProperties().GetPropertyInfoTestTypeTrimmed(testTypeClass), expected, errorCode); +} + +static int CheckType(Type type, string expected, int errorCode) +{ + TestType testTypeClass = new(); + return FailIfNotEqual(new SetTypeProperties().GetPropertyInfoTestType(testTypeClass, type), expected, errorCode); +} + +static int FailIfNotEqual(string actual, string expected, int errorCode) +{ + if (actual != expected) + { + return errorCode; + } + + return 0; +} + +readonly record struct TypeCase(Type Type, string Name, string Kind, int ErrorCode); + +sealed class TestType : IType +{ + public Type TypeProperty { get; set; } +} + +sealed class TestCSharp +{ +} + +interface ITestCSharp +{ +} + +delegate void DelegateTestCSharp(object sender, T value); \ No newline at end of file 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 6633649f5..8a0895090 100644 --- a/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.cpp +++ b/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.cpp @@ -5,9 +5,65 @@ #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::GetPropertyInfoTestType( + IType const& testObject, + Windows::UI::Xaml::Interop::TypeName const& typeName) + { + testObject.TypeProperty(typeName); + Windows::UI::Xaml::Interop::TypeName testProperty = testObject.TypeProperty(); + winrt::hstring kind; + switch (testProperty.Kind) + { + case Windows::UI::Xaml::Interop::TypeKind::Custom: + kind = winrt::hstring(L"Custom"); + break; + case Windows::UI::Xaml::Interop::TypeKind::Metadata: + kind = winrt::hstring(L"Metadata"); + break; + default: + kind = winrt::hstring(L"Primitive"); + break; + } + return testProperty.Name + L" " + kind; + } + + winrt::hstring SetTypeProperties::GetPropertyInfoTestTypeTrimmed(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"); + break; + case Windows::UI::Xaml::Interop::TypeKind::Metadata: + kind = winrt::hstring(L"Metadata"); + break; + default: + kind = winrt::hstring(L"Primitive"); + break; + } + return testObject.TypeProperty().Name + L" " + kind; + } + + winrt::hstring SetTypeProperties::GetPropertyInfoWithType(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..323555a79 100644 --- a/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.h +++ b/src/Tests/TestComponentCSharp/ManualProjectionTestClasses.h @@ -4,9 +4,19 @@ #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 GetPropertyInfoTestTypeTrimmed(IType testObject); + winrt::hstring GetPropertyInfoWithType(winrt::Windows::UI::Xaml::Interop::TypeName typeName); + winrt::hstring GetPropertyInfoTestType(IType const& testObject, Windows::UI::Xaml::Interop::TypeName const& typeName); + }; + struct CustomBindableIteratorTest : CustomBindableIteratorTestT { CustomBindableIteratorTest(); @@ -72,6 +82,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 ce2b1eeb5..0ac3a0d82 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; }; @@ -153,6 +158,25 @@ namespace TestComponentCSharp } [default_interface] + runtimeclass SetTypeProperties + { + SetTypeProperties(); + String GetPropertyInfoTestTypeTrimmed(IType testObject); + String GetPropertyInfoWithType(Windows.UI.Xaml.Interop.TypeName typeName); + String GetPropertyInfoTestType(IType testObject, Windows.UI.Xaml.Interop.TypeName typeName); + } + + // Do not reference TestComponentCSharp::TestTypeTrimmed in managed because it needs to be trimmed to test the Metadata TypeKind scenario in the TypeHandling project + runtimeclass TestTypeTrimmed + { + void f(); + } + + runtimeclass TestType + { + void f(); + } + unsealed runtimeclass UnSealedCustomEquals { Int32 Value{ get; set; }; 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 706b051f6..fbc857446 100644 --- a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs +++ b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs @@ -1,47 +1,82 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Linq; using System.Numerics; +using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Runtime.InteropServices.WindowsRuntime; using System.Threading; using System.Threading.Tasks; -using Xunit; - -using Windows.Foundation; -using Windows.UI; -using Windows.Storage; -using Windows.Storage.Streams; +using System.Windows.Input; +using ABI.System.Collections.Specialized; +using ABI.System.ComponentModel; +using ABI.Windows.Foundation.Collections; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Interop; using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Media.Media3D; - using TestComponentCSharp; -using System.Collections.Generic; -using System.Collections; -using WinRT.Interop; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Devices.Enumeration; +using Windows.Devices.Enumeration.Pnp; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.Foundation.Tasks; using Windows.Security.Cryptography; using Windows.Security.Cryptography.Core; -using System.Reflection; -using Windows.Devices.Enumeration.Pnp; -using System.Diagnostics; -using Windows.Devices.Enumeration; +using Windows.Storage; +using Windows.Storage.Streams; +using Windows.UI; using Windows.UI.Notifications; -using WindowsRuntime.InteropServices.Marshalling; -using WindowsRuntime.InteropServices; using WindowsRuntime; -using System.Runtime.InteropServices.Marshalling; -using Windows.Foundation.Tasks; +using WindowsRuntime.InteropServices; +using WindowsRuntime.InteropServices.Marshalling; +using WinRT.Interop; +using Xunit; +using Xunit.Sdk; +using static System.Diagnostics.Activity; // Test SupportedOSPlatform warnings for APIs targeting 10.0.19041.0: [assembly: global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.18362.0")] namespace UnitTest { + [CLSCompliant(false)] + [DataDiscoverer("Xunit.Sdk.InlineDataDiscoverer", "xunit.core")] + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] + public sealed class InlineDataAttribute : DataAttribute + { + private readonly object[] data; + + public InlineDataAttribute(params object[] data) + { + this.data = data; + } + + public override IEnumerable GetData(MethodInfo testMethod) + { + object[] arguments = [typeof(T), .. data]; + + return [arguments]; + } + } + + public delegate void DelegateTestCSharp(); + + public interface ITestCSharp + { + void TestMethod(); + } + public partial class TestCSharp { public Class TestObject { get; private set; } @@ -547,12 +582,139 @@ 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] + // Mapped System.* Types Primitive Types + [InlineData(typeof(bool), "Boolean", "Primitive")] + [InlineData(typeof(byte), "UInt8", "Primitive")] + [InlineData(typeof(char), "Char16", "Primitive")] + [InlineData(typeof(double), "Double", "Primitive")] + [InlineData(typeof(short), "Int16", "Primitive")] + [InlineData(typeof(int), "Int32", "Primitive")] + [InlineData(typeof(long), "Int64", "Primitive")] + [InlineData(typeof(float), "Single", "Primitive")] + [InlineData(typeof(ushort), "UInt16", "Primitive")] + [InlineData(typeof(uint), "UInt32", "Primitive")] + [InlineData(typeof(ulong), "UInt64", "Primitive")] + // Mapped System.* Types Metadata Types + [InlineData(typeof(DateTimeOffset), "Windows.Foundation.DateTime", "Metadata")] + [InlineData>(typeof(EventHandler), "Windows.Foundation.EventHandler`1", "Metadata")] + [InlineData(typeof(Exception), "Windows.Foundation.HResult", "Metadata")] + [InlineData(typeof(Guid), "Guid", "Metadata")] + [InlineData(typeof(IDisposable), "Windows.Foundation.IClosable", "Metadata")] + [InlineData(typeof(IServiceProvider), "Microsoft.UI.Xaml.IXamlServiceProvider", "Metadata")] + [InlineData(typeof(object), "Object", "Metadata")] + [InlineData(typeof(string), "String", "Metadata")] + [InlineData(typeof(TimeSpan), "Windows.Foundation.TimeSpan", "Metadata")] + [InlineData(typeof(Type), "Windows.UI.Xaml.Interop.TypeName", "Metadata")] + [InlineData(typeof(Uri), "Windows.Foundation.Uri", "Metadata")] + [InlineData(typeof(ICommand), "Microsoft.UI.Xaml.Input.ICommand", "Metadata")] + // Mapped System.Collections.* Types + [InlineData(typeof(IEnumerable), "Microsoft.UI.Xaml.Interop.IBindableIterable", "Metadata")] + [InlineData(typeof(IEnumerator), "Microsoft.UI.Xaml.Interop.IBindableIterator", "Metadata")] + [InlineData(typeof(IList), "Microsoft.UI.Xaml.Interop.IBindableVector", "Metadata")] + [InlineData>(typeof(IReadOnlyList), "Windows.Foundation.Collections.IVectorView`1", "Metadata")] + // Mapped System.Collections.Specialized* Types + [InlineData(typeof(INotifyCollectionChanged), "Microsoft.UI.Xaml.Interop.INotifyCollectionChanged", "Metadata")] + [InlineData(typeof(NotifyCollectionChangedEventArgs), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", "Metadata")] + [InlineData(typeof(NotifyCollectionChangedEventHandler), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventHandler", "Metadata")] + // Mapped System.ComponentModel.* Types + [InlineData(typeof(DataErrorsChangedEventArgs), "Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs", "Metadata")] + [InlineData(typeof(INotifyDataErrorInfo), "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo", "Metadata")] + [InlineData(typeof(INotifyPropertyChanged), "Microsoft.UI.Xaml.Data.INotifyPropertyChanged", "Metadata")] + [InlineData(typeof(PropertyChangedEventArgs), "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs", "Metadata")] + [InlineData(typeof(PropertyChangedEventHandler), "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler", "Metadata")] + // Mapped System.Numerics.* Types + [InlineData(typeof(Matrix3x2), "Windows.Foundation.Numerics.Matrix3x2", "Metadata")] + [InlineData(typeof(Matrix4x4), "Windows.Foundation.Numerics.Matrix4x4", "Metadata")] + [InlineData(typeof(Plane), "Windows.Foundation.Numerics.Plane", "Metadata")] + [InlineData(typeof(Quaternion), "Windows.Foundation.Numerics.Quaternion", "Metadata")] + [InlineData(typeof(Vector2), "Windows.Foundation.Numerics.Vector2", "Metadata")] + [InlineData(typeof(Vector3), "Windows.Foundation.Numerics.Vector3", "Metadata")] + [InlineData(typeof(Vector4), "Windows.Foundation.Numerics.Vector4", "Metadata")] + // Mapped Windows.Foundation.* Types + [InlineData(typeof(AsyncActionCompletedHandler), "Windows.Foundation.AsyncActionCompletedHandler", "Metadata")] + [InlineData(typeof(IAsyncAction), "Windows.Foundation.IAsyncAction", "Metadata")] + [InlineData(typeof(IAsyncInfo), "Windows.Foundation.IAsyncInfo", "Metadata")] + [InlineData(typeof(Point), "Windows.Foundation.Point", "Metadata")] + [InlineData(typeof(Rect), "Windows.Foundation.Rect", "Metadata")] + [InlineData(typeof(Size), "Windows.Foundation.Size", "Metadata")] + [InlineData(typeof(IStringable), "Windows.Foundation.IStringable", "Metadata")] + // Mapped Windows.Foundation.Collections.* Types + [InlineData(typeof(CollectionChange), "Windows.Foundation.Collections.CollectionChange", "Metadata")] + [InlineData(typeof(IVectorChangedEventArgs), "Windows.Foundation.Collections.IVectorChangedEventArgs", "Metadata")] + // Mapped WindowsRuntime.InteropServices.* Types + [InlineData(typeof(EventRegistrationToken), "WindowsRuntime.InteropServices.EventRegistrationToken", "Metadata")] + // Others + [InlineData(typeof(NotifyCollectionChangedAction), "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedAction", "Metadata")] + [InlineData(typeof(NotifyCollectionChangedAction?), "Windows.Foundation.IReference`1", "Metadata")] + // Projected WinRT Types + [InlineData(typeof(TestComponent.Class), "TestComponent.Class", "Metadata")] + [InlineData(typeof(TestComponent.Nested), "TestComponent.Nested", "Metadata")] + [InlineData(typeof(TestComponent.IRequiredOne), "TestComponent.IRequiredOne", "Metadata")] + [InlineData(typeof(TestComponent.Param6Handler), "TestComponent.Param6Handler", "Metadata")] + [InlineData(typeof(TestComponentCSharp.Class), "TestComponentCSharp.Class", "Metadata")] + [InlineData(typeof(TestComponentCSharp.ComposedBlittableStruct), "TestComponentCSharp.ComposedBlittableStruct", "Metadata")] + [InlineData(typeof(TestComponentCSharp.IArtist), "TestComponentCSharp.IArtist", "Metadata")] + [InlineData(typeof(TestComponentCSharp.EnumValue), "TestComponentCSharp.EnumValue", "Metadata")] + [InlineData(typeof(TestComponentCSharp.EventHandler0), "TestComponentCSharp.EventHandler0", "Metadata")] + // Nullable Types + [InlineData(typeof(long?), "Windows.Foundation.IReference`1", "Metadata")] + [InlineData(typeof(Point?), "Windows.Foundation.IReference`1", "Metadata")] + [InlineData(typeof(Vector3?), "Windows.Foundation.IReference`1", "Metadata")] + [InlineData(typeof(Guid?), "Windows.Foundation.IReference`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.EnumValue?), "Windows.Foundation.IReference`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.BlittableStruct?), "Windows.Foundation.IReference`1", "Metadata")] + [InlineData>(typeof(IList), "Windows.Foundation.Collections.IVector`1>", "Metadata")] + [InlineData(typeof(Int32?[]), "Windows.Foundation.IReferenceArray`1>", "Metadata")] + // Generic Types + [InlineData>(typeof(IList), "Windows.Foundation.Collections.IVector`1", "Metadata")] + [InlineData>(typeof(IList), "Windows.Foundation.Collections.IVector`1", "Metadata")] // Using the fully qualified asssembly name + [InlineData>(typeof(IList), "Windows.Foundation.Collections.IVector`1", "Metadata")] // Using the fully qualified asssembly name + [InlineData>(typeof(IEnumerator), "Windows.Foundation.Collections.IIterator`1", "Metadata")] + [InlineData>(typeof(IEnumerable), "Windows.Foundation.Collections.IIterable`1", "Metadata")] + [InlineData>(typeof(EventHandler), "Windows.Foundation.EventHandler`1", "Metadata")] + [InlineData>(typeof(KeyValuePair), "Windows.Foundation.Collections.IKeyValuePair`2", "Metadata")] + [InlineData>(typeof(KeyValuePair), "Windows.Foundation.Collections.IKeyValuePair`2", "Metadata")] + [InlineData>(typeof(KeyValuePair), "Windows.Foundation.Collections.IKeyValuePair`2", "Metadata")] + // Nested Generics + [InlineData>>(typeof(EventHandler>), "Windows.Foundation.EventHandler`1>", "Metadata")] + [InlineData>>(typeof(EventHandler>), "Windows.Foundation.EventHandler`1>", "Metadata")] + [InlineData>>(typeof(EventHandler>), "Windows.Foundation.EventHandler`1>", "Metadata")] + [InlineData>>(typeof(IList>), "Windows.Foundation.Collections.IVector`1>", "Metadata")] + [InlineData>>(typeof(IEnumerator>), "Windows.Foundation.Collections.IIterator`1>", "Metadata")] + [InlineData>>(typeof(IEnumerable>), "Windows.Foundation.Collections.IIterable`1>", "Metadata")] + // Custom Types + [InlineData(typeof(TestCSharp), "UnitTest.TestCSharp, UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Custom")] + [InlineData>(typeof(IList), "System.Collections.Generic.IList`1[[UnitTest.TestCSharp, UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>(typeof(ITestCSharp), "UnitTest.ITestCSharp`1[[System.Double, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Custom")] + [InlineData>(typeof(KeyValuePair), "System.Collections.Generic.KeyValuePair`2[[System.String, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[UnitTest.TestCSharp, UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>>(typeof(EventHandler>), "System.EventHandler`1[[System.Collections.Generic.IList`1[[UnitTest.TestCSharp, UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>(typeof(EventHandler), "System.EventHandler`1[[UnitTest.TestCSharp, UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>(typeof(DelegateTestCSharp), "UnitTest.DelegateTestCSharp`1[[System.Guid, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], UnitTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Custom")] + [InlineData>(typeof(WeakReference), "System.WeakReference`1[[TestComponent.Class, WinRT.Projection, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>>(typeof(KeyValuePair>), "System.Collections.Generic.KeyValuePair`2[[System.Int32, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.WeakReference`1[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>(typeof(ICollection), "System.Collections.Generic.ICollection`1[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData?>(typeof(KeyValuePair?), "System.Nullable`1[[System.Collections.Generic.KeyValuePair`2[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData>(typeof(KeyValuePair), "System.Collections.Generic.KeyValuePair`2[[System.Object, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object[], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + [InlineData(typeof(long[][]), "System.Int64[][], System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e", "Custom")] + // Arrays + [InlineData(typeof(Object[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(long[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.Class[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.ComposedBlittableStruct[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.IArtist[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.EnumValue[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(TestComponentCSharp.EventHandler0[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData(typeof(Point[]), "Windows.Foundation.IReferenceArray`1", "Metadata")] + [InlineData[]>(typeof(IList[]), "Windows.Foundation.IReferenceArray`1>", "Metadata")] + [InlineData[]>(typeof(IList[]), "Windows.Foundation.IReferenceArray`1>>", "Metadata")] + [InlineData[]>(typeof(KeyValuePair[]), "Windows.Foundation.IReferenceArray`1>", "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 { } @@ -2702,15 +2864,16 @@ public void TestGetRuntimeClassName() IList arr4 = new List() { E.A, E.B, E.C }; Array arr5 = new PropertyType[] { PropertyType.UInt8, PropertyType.Int16, PropertyType.UInt16 }; - Assert.Equal(string.Empty, Class.GetName(arr)); - Assert.Equal(string.Empty, Class.GetName(arr2)); + // TODO: Enable once non WinRT arrays are supported. + // Assert.Equal(string.Empty, Class.GetName(arr)); + // Assert.Equal(string.Empty, Class.GetName(arr2)); Assert.Equal("Windows.Foundation.IReferenceArray`1", Class.GetName(arr3)); Assert.Equal("Microsoft.UI.Xaml.Interop.IBindableVector", Class.GetName(arr4)); Assert.Equal("Windows.Foundation.IReferenceArray`1", Class.GetName(arr5)); - Assert.Equal(string.Empty, Class.GetName(arr.GetValue(0))); - Assert.Equal(string.Empty, Class.GetName(arr2.GetValue(0))); + // Assert.Equal(string.Empty, Class.GetName(arr.GetValue(0))); + // Assert.Equal(string.Empty, Class.GetName(arr2.GetValue(0))); Assert.Equal("Windows.Foundation.IReference`1", Class.GetName(arr3.GetValue(0))); - Assert.Equal(string.Empty, Class.GetName(arr4[0])); + // Assert.Equal(string.Empty, Class.GetName(arr4[0])); Assert.Equal("Windows.Foundation.IReference`1", Class.GetName(arr5.GetValue(0))); Assert.Equal("Windows.Foundation.IReference`1", Class.GetName(typeof(IProperties1))); @@ -3207,7 +3370,6 @@ public void TestIBindableIterator() { CustomBindableIteratorTest bindableIterator = new CustomBindableIteratorTest(); Assert.True(bindableIterator.MoveNext()); - Assert.True(bindableIterator.HasCurrent); Assert.Equal(27861, bindableIterator.Current); } @@ -3432,34 +3594,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/UnitTest.csproj b/src/Tests/UnitTest/UnitTest.csproj index 94a990f33..7d4aab198 100644 --- a/src/Tests/UnitTest/UnitTest.csproj +++ b/src/Tests/UnitTest/UnitTest.csproj @@ -10,11 +10,12 @@ + - + diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs new file mode 100644 index 000000000..0b8c49f38 --- /dev/null +++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.ICommand.cs @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; +using WindowsRuntime.InteropGenerator.Factories; +using WindowsRuntime.InteropGenerator.References; + +namespace WindowsRuntime.InteropGenerator.Builders; + +/// +internal partial class DynamicCustomMappedTypeMapEntriesBuilder +{ + /// + /// Helpers for the type. + /// + public static class ICommand + { + /// + /// Creates a new type definition for the interface implementation of the interface. + /// + /// The instance to use. + /// The module that will contain the type being created. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting interface implementation type. + public static void InterfaceImpl( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + out TypeDefinition interfaceImplType) + { + TypeSignature interfaceType = interopReferences.ICommand.ToReferenceTypeSignature(); + + // We're declaring an 'internal interface class' type + interfaceImplType = new( + ns: InteropUtf8NameFactory.TypeNamespace(interfaceType), + name: InteropUtf8NameFactory.TypeName(interfaceType, "InterfaceImpl"), + attributes: TypeAttributes.Interface | TypeAttributes.AutoLayout | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit, + baseType: null) + { + CustomAttributes = + { + new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor.Import(module)), + InteropCustomAttributeFactory.Guid(interfaceType, interopReferences, module, useWindowsUIXamlProjections) + }, + Interfaces = { new InterfaceImplementation(interfaceType.Import(module).ToTypeDefOrRef()) } + }; + + module.TopLevelTypes.Add(interfaceImplType); + + // Create the 'ICommand.CanExecuteChanged' add method + MethodDefinition add_ICommandCanExecuteChangedMethod = new( + name: "System.Windows.Input.ICommand.add_CanExecuteChanged", + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceAccessorMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [interopReferences.EventHandler.Import(module).ToReferenceTypeSignature()])) + { + CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + handlerType: interopReferences.EventHandler.ToReferenceTypeSignature(), + eventMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("CanExecuteChanged"u8), + eventAccessorAttributes: MethodSemanticsAttributes.AddOn, + interopReferences: interopReferences, + module: module) + }; + + // Add and implement the 'ICommand.CanExecuteChanged' add accessor method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.ICommandadd_CanExecuteChanged.Import(module), + method: add_ICommandCanExecuteChangedMethod); + + // Create the 'ICommand.CanExecuteChanged' remove method + MethodDefinition remove_ICommandCanExecuteChangedMethod = new( + name: "System.Windows.Input.ICommand.remove_CanExecuteChanged", + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceAccessorMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [interopReferences.EventHandler.Import(module).ToReferenceTypeSignature()])) + { + CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + handlerType: interopReferences.EventHandler.ToReferenceTypeSignature(), + eventMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("CanExecuteChanged"u8), + eventAccessorAttributes: MethodSemanticsAttributes.RemoveOn, + interopReferences: interopReferences, + module: module) + }; + + // Add and implement the 'ICommand.CanExecuteChanged' remove accessor method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.ICommandremove_CanExecuteChanged.Import(module), + method: remove_ICommandCanExecuteChangedMethod); + + // Create the 'ICommand.CanExecuteChanged' event + EventDefinition canExecuteChangedProperty = new( + name: "System.Windows.Input.ICommand.CanExecuteChanged", + attributes: default, + eventType: interopReferences.EventHandler.Import(module)) + { + AddMethod = add_ICommandCanExecuteChangedMethod, + RemoveMethod = remove_ICommandCanExecuteChangedMethod + }; + + interfaceImplType.Events.Add(canExecuteChangedProperty); + + // Define the 'ICommand.CanExecute' method + MethodDefinition canExecuteMethod = new( + name: "System.Windows.Input.ICommand.CanExecute"u8, + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Boolean, + parameterTypes: [module.CorLibTypeFactory.Object])); + + // Add and implement the 'CanExecute' method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.ICommandCanExecute.Import(module), + method: canExecuteMethod); + + // Create a method body for the 'CanExecute' method + canExecuteMethod.CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + implementationMethod: canExecuteMethod, + forwardedMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("CanExecute"u8), + interopReferences: interopReferences, + module: module); + + // Define the 'ICommand.Execute' method + MethodDefinition executeMethod = new( + name: "System.Windows.Input.ICommand.Execute"u8, + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [module.CorLibTypeFactory.Object])); + + // Add and implement the 'Execute' method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.ICommandExecute.Import(module), + method: executeMethod); + + // Create a method body for the 'Execute' method + executeMethod.CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + implementationMethod: executeMethod, + forwardedMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("Execute"u8), + interopReferences: interopReferences, + module: module); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs new file mode 100644 index 000000000..8846556ff --- /dev/null +++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyCollectionChanged.cs @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; +using WindowsRuntime.InteropGenerator.Factories; +using WindowsRuntime.InteropGenerator.References; + +namespace WindowsRuntime.InteropGenerator.Builders; + +/// +internal partial class DynamicCustomMappedTypeMapEntriesBuilder +{ + /// + /// Helpers for the type. + /// + public static class INotifyCollectionChanged + { + /// + /// Creates a new type definition for the interface implementation of the interface. + /// + /// The instance to use. + /// The module that will contain the type being created. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting interface implementation type. + public static void InterfaceImpl( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + out TypeDefinition interfaceImplType) + { + TypeSignature interfaceType = interopReferences.INotifyCollectionChanged.ToReferenceTypeSignature(); + + // We're declaring an 'internal interface class' type + interfaceImplType = new( + ns: InteropUtf8NameFactory.TypeNamespace(interfaceType), + name: InteropUtf8NameFactory.TypeName(interfaceType, "InterfaceImpl"), + attributes: TypeAttributes.Interface | TypeAttributes.AutoLayout | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit, + baseType: null) + { + CustomAttributes = + { + new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor.Import(module)), + InteropCustomAttributeFactory.Guid(interfaceType, interopReferences, module, useWindowsUIXamlProjections) + }, + Interfaces = { new InterfaceImplementation(interfaceType.Import(module).ToTypeDefOrRef()) } + }; + + module.TopLevelTypes.Add(interfaceImplType); + + // Create the 'INotifyCollectionChanged.CollectionChanged' add method + MethodDefinition add_INotifyCollectionChangedCollectionChangedMethod = new( + name: "System.Collections.Specialized.INotifyCollectionChanged.add_CollectionChanged", + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceAccessorMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [interopReferences.NotifyCollectionChangedEventHandler.Import(module).ToReferenceTypeSignature()])) + { + CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + handlerType: interopReferences.NotifyCollectionChangedEventHandler.ToReferenceTypeSignature(), + eventMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("CollectionChanged"u8), + eventAccessorAttributes: MethodSemanticsAttributes.AddOn, + interopReferences: interopReferences, + module: module) + }; + + // Add and implement the 'INotifyCollectionChanged.CollectionChanged' add accessor method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.INotifyCollectionChangedadd_CollectionChanged.Import(module), + method: add_INotifyCollectionChangedCollectionChangedMethod); + + // Create the 'INotifyCollectionChanged.CollectionChanged' remove method + MethodDefinition remove_INotifyCollectionChangedCollectionChangedMethod = new( + name: "System.Collections.Specialized.INotifyCollectionChanged.remove_CollectionChanged", + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceAccessorMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [interopReferences.NotifyCollectionChangedEventHandler.Import(module).ToReferenceTypeSignature()])) + { + CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + handlerType: interopReferences.NotifyCollectionChangedEventHandler.ToReferenceTypeSignature(), + eventMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("CollectionChanged"u8), + eventAccessorAttributes: MethodSemanticsAttributes.RemoveOn, + interopReferences: interopReferences, + module: module) + }; + + // Add and implement the 'INotifyCollectionChanged.CollectionChanged' remove accessor method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.INotifyCollectionChangedremove_CollectionChanged.Import(module), + method: remove_INotifyCollectionChangedCollectionChangedMethod); + + // Create the 'INotifyCollectionChanged.CollectionChanged' event + EventDefinition collectionChangedProperty = new( + name: "System.Collections.Specialized.INotifyCollectionChanged.CollectionChanged", + attributes: default, + eventType: interopReferences.NotifyCollectionChangedEventHandler.Import(module)) + { + AddMethod = add_INotifyCollectionChangedCollectionChangedMethod, + RemoveMethod = remove_INotifyCollectionChangedCollectionChangedMethod + }; + + interfaceImplType.Events.Add(collectionChangedProperty); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs new file mode 100644 index 000000000..34a966243 --- /dev/null +++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.INotifyPropertyChanged.cs @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Metadata.Tables; +using WindowsRuntime.InteropGenerator.Factories; +using WindowsRuntime.InteropGenerator.References; + +namespace WindowsRuntime.InteropGenerator.Builders; + +/// +internal partial class DynamicCustomMappedTypeMapEntriesBuilder +{ + /// + /// Helpers for the type. + /// + public static class INotifyPropertyChanged + { + /// + /// Creates a new type definition for the interface implementation of the interface. + /// + /// The instance to use. + /// The module that will contain the type being created. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting interface implementation type. + public static void InterfaceImpl( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + out TypeDefinition interfaceImplType) + { + TypeSignature interfaceType = interopReferences.INotifyPropertyChanged.ToReferenceTypeSignature(); + + // We're declaring an 'internal interface class' type + interfaceImplType = new( + ns: InteropUtf8NameFactory.TypeNamespace(interfaceType), + name: InteropUtf8NameFactory.TypeName(interfaceType, "InterfaceImpl"), + attributes: TypeAttributes.Interface | TypeAttributes.AutoLayout | TypeAttributes.Abstract | TypeAttributes.BeforeFieldInit, + baseType: null) + { + CustomAttributes = + { + new CustomAttribute(interopReferences.DynamicInterfaceCastableImplementationAttribute_ctor.Import(module)), + InteropCustomAttributeFactory.Guid(interfaceType, interopReferences, module, useWindowsUIXamlProjections) + }, + Interfaces = { new InterfaceImplementation(interfaceType.Import(module).ToTypeDefOrRef()) } + }; + + module.TopLevelTypes.Add(interfaceImplType); + + // Create the 'INotifyPropertyChanged.PropertyChanged' add method + MethodDefinition add_INotifyPropertyChangedPropertyChangedMethod = new( + name: "System.ComponentModel.INotifyPropertyChanged.add_PropertyChanged", + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceAccessorMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [interopReferences.PropertyChangedEventHandler.Import(module).ToReferenceTypeSignature()])) + { + CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + handlerType: interopReferences.PropertyChangedEventHandler.ToReferenceTypeSignature(), + eventMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("PropertyChanged"u8), + eventAccessorAttributes: MethodSemanticsAttributes.AddOn, + interopReferences: interopReferences, + module: module) + }; + + // Add and implement the 'INotifyPropertyChanged.PropertyChanged' add accessor method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.INotifyPropertyChangedadd_PropertyChanged.Import(module), + method: add_INotifyPropertyChangedPropertyChangedMethod); + + // Create the 'INotifyPropertyChanged.PropertyChanged' remove method + MethodDefinition remove_INotifyPropertyChangedPropertyChangedMethod = new( + name: "System.ComponentModel.INotifyPropertyChanged.remove_PropertyChanged", + attributes: WellKnownMethodAttributesFactory.ExplicitInterfaceImplementationInstanceAccessorMethod, + signature: MethodSignature.CreateInstance( + returnType: module.CorLibTypeFactory.Void, + parameterTypes: [interopReferences.PropertyChangedEventHandler.Import(module).ToReferenceTypeSignature()])) + { + CilMethodBody = WellKnownCilMethodBodyFactory.DynamicInterfaceCastableImplementation( + interfaceType: interfaceType, + handlerType: interopReferences.PropertyChangedEventHandler.ToReferenceTypeSignature(), + eventMethod: GetMethodsType(interfaceType, interopReferences, module).GetMethod("PropertyChanged"u8), + eventAccessorAttributes: MethodSemanticsAttributes.RemoveOn, + interopReferences: interopReferences, + module: module) + }; + + // Add and implement the 'INotifyPropertyChanged.PropertyChanged' remove accessor method + interfaceImplType.AddMethodImplementation( + declaration: interopReferences.INotifyPropertyChangedremove_PropertyChanged.Import(module), + method: remove_INotifyPropertyChangedPropertyChangedMethod); + + // Create the 'INotifyPropertyChanged.PropertyChanged' event + EventDefinition propertyChangedProperty = new( + name: "System.ComponentModel.INotifyPropertyChanged.PropertyChanged", + attributes: default, + eventType: interopReferences.PropertyChangedEventHandler.Import(module)) + { + AddMethod = add_INotifyPropertyChangedPropertyChangedMethod, + RemoveMethod = remove_INotifyPropertyChangedPropertyChangedMethod + }; + + interfaceImplType.Events.Add(propertyChangedProperty); + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs index 8b23ff529..189e28a93 100644 --- a/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs +++ b/src/WinRT.Interop.Generator/Builders/DynamicCustomMappedTypeMapEntriesBuilder.cs @@ -9,8 +9,11 @@ using WindowsRuntime.InteropGenerator.Errors; using WindowsRuntime.InteropGenerator.Factories; using WindowsRuntime.InteropGenerator.Generation; +using WindowsRuntime.InteropGenerator.Helpers; using WindowsRuntime.InteropGenerator.References; +#pragma warning disable IDE0046 + namespace WindowsRuntime.InteropGenerator.Builders; /// @@ -29,109 +32,365 @@ public static void AssemblyAttributes( InteropReferences interopReferences, ModuleDefinition module) { - ManagedOnlyTypeOrInterface( - args: args, - windowsUIXamlTypeName: "Windows.UI.Xaml.Interop.IBindableIterable", - microsoftUIXamlTypeName: "Microsoft.UI.Xaml.Interop.IBindableIterable", - target: interopReferences.WindowsRuntimeModule.CreateTypeReference("ABI.System.Collections"u8, "IEnumerable"u8).ToReferenceTypeSignature(), + InterfaceType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.IEnumerable.ToReferenceTypeSignature(), interopReferences: interopReferences, - module: module); + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections, + useComWrappersMarshallerAttribute: true); - ManagedOnlyTypeOrInterface( - args: args, - windowsUIXamlTypeName: "Windows.UI.Xaml.Interop.IBindableIterator", - microsoftUIXamlTypeName: "Microsoft.UI.Xaml.Interop.IBindableIterator", - target: interopReferences.WindowsRuntimeModule.CreateTypeReference("ABI.System.Collections"u8, "IEnumerator"u8).ToReferenceTypeSignature(), + InterfaceType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.IEnumerator.ToReferenceTypeSignature(), interopReferences: interopReferences, - module: module); + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections, + useComWrappersMarshallerAttribute: true); - ManagedOnlyTypeOrInterface( - args: args, - windowsUIXamlTypeName: "Windows.UI.Xaml.Interop.IBindableVector", - microsoftUIXamlTypeName: "Microsoft.UI.Xaml.Interop.IBindableVector", - target: interopReferences.WindowsRuntimeModule.CreateTypeReference("ABI.System.Collections"u8, "IList"u8).ToReferenceTypeSignature(), + InterfaceType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.IList.ToReferenceTypeSignature(), interopReferences: interopReferences, - module: module); + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections, + useComWrappersMarshallerAttribute: true); - ManagedOnlyTypeOrInterface( - args: args, - windowsUIXamlTypeName: "Windows.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", - microsoftUIXamlTypeName: "Microsoft.UI.Xaml.Interop.NotifyCollectionChangedEventArgs", - target: interopReferences.WindowsRuntimeModule.CreateTypeReference("ABI.System.Collections.Specialized"u8, "NotifyCollectionChangedEventArgs"u8).ToReferenceTypeSignature(), + ICommandInterfaceType( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); + + INotifyCollectionChangedInterfaceType( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); + + INotifyPropertyChangedInterfaceType( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); + + ClassType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.NotifyCollectionChangedEventArgs.ToReferenceTypeSignature(), interopReferences: interopReferences, - module: module); + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); - ManagedOnlyTypeOrInterface( - args: args, - windowsUIXamlTypeName: "Windows.UI.Xaml.Data.PropertyChangedEventArgs", - microsoftUIXamlTypeName: "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs", - target: interopReferences.WindowsRuntimeModule.CreateTypeReference("ABI.System.ComponentModel"u8, "PropertyChangedEventArgs"u8).ToReferenceTypeSignature(), + ClassType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.PropertyChangedEventArgs.ToReferenceTypeSignature(), interopReferences: interopReferences, - module: module); + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); - WindowsRuntimeExposedType( - args: args, - windowsUIXamlTypeName: "Windows.Foundation.IReference`1", - microsoftUIXamlTypeName: "Windows.Foundation.IReference`1", + DelegateType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.NotifyCollectionChangedEventHandler.ToReferenceTypeSignature(), interopReferences: interopReferences, - module: module); + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); - WindowsRuntimeExposedType( - args: args, - windowsUIXamlTypeName: "Windows.Foundation.IReference`1", - microsoftUIXamlTypeName: "Windows.Foundation.IReference`1", + DelegateType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", trimTarget: interopReferences.PropertyChangedEventHandler.ToReferenceTypeSignature(), interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); + + ValueType( + windowsUIXamlMetadata: "Windows.Foundation.UniversalApiContract", + microsoftUIXamlMetadata: "Microsoft.UI.Xaml.WinUIContract", + trimTarget: interopReferences.NotifyCollectionChangedAction.ToValueTypeSignature(), + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); + + IBindableVectorViewType( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: args.UseWindowsUIXamlProjections); + } + + /// + /// Creates a new custom attribute value for for a given custom-mapped interface type. + /// + /// The metadata name for Windows.UI.Xaml. + /// The metadata name for Microsoft.UI.Xaml. + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// Whether to use Windows.UI.Xaml projections. + /// Whether to also use the [WindowsRuntimeComWrappersMarshaller] attribute for . + private static void InterfaceType( + string windowsUIXamlMetadata, + string microsoftUIXamlMetadata, + TypeSignature trimTarget, + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + bool useComWrappersMarshallerAttribute) + { + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; + + // Only lookup the '[WindowsRuntimeComWrappersMarshaller]' attribute if requested. For instance, types such as 'IEnumerable' + // will need one, so they can plug in specialized RCWs to better handle all the various scenarios where the interface is + // used. Other interfaces, such as 'INotifyPropertyChanged', don't need that, and they will just rely on dynamic casts. + TypeDefinition? comWrappersMarshallerAttribute = useComWrappersMarshallerAttribute + ? GetMarshallerAttributeType(trimTarget, interopReferences, module) + : null; + + // Define the proxy type for the interface type. Because the metadata type name depends on the XAML configuration + // that is used, we can't define this proxy type in advance even if the interface type itself is not generic. + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + mappedType: trimTarget, + referenceType: null, + comWrappersMarshallerAttributeType: comWrappersMarshallerAttribute, + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); + + // For interface types (such as 'IEnumerable'), which don't need CCW support (because they are interfaces), we just + // need the marshalling type map entry to support anonymous objects, and a metadata proxy type map entry to retrieve + // the correct metadata info when marshalling 'Type' instances. We don't need to emit entries in the dynamic interface + // castable type map, because those attributes are in 'WinRT.Runtime.dll' already (as the types are not generic). + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + externalTypeMapTargetType: proxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: trimTarget, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: trimTarget, + metadataTypeMapProxyType: proxyType.ToTypeSignature(), + interfaceTypeMapSourceType: null, + interfaceTypeMapProxyType: null, + interopReferences: interopReferences, module: module); + } - WindowsRuntimeExposedType( - args: args, - windowsUIXamlTypeName: "Windows.UI.Xaml.Interop.IBindableVectorView", - microsoftUIXamlTypeName: "Microsoft.UI.Xaml.Interop.IBindableVectorView", - trimTarget: interopReferences.BindableIReadOnlyListAdapter.ToReferenceTypeSignature(), + /// + /// Creates a new custom attribute value for for the interface type. + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// Whether to use Windows.UI.Xaml projections. + private static void ICommandInterfaceType( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections) + { + const string windowsUIXamlMetadata = "Windows.Foundation.UniversalApiContract"; + const string microsoftUIXamlMetadata = "Microsoft.UI.Xaml.WinUIContract"; + + TypeSignature trimTarget = interopReferences.ICommand.ToReferenceTypeSignature(); + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; + + // Define the proxy type for the 'ICommand' interface type (it needs a dynamic one, same as the other interface types above) + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + mappedType: trimTarget, + referenceType: null, + comWrappersMarshallerAttributeType: null, + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); + + // Define the 'InterfaceImpl' type for the 'ICommand' interface type + ICommand.InterfaceImpl( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: useWindowsUIXamlProjections, + interfaceImplType: out TypeDefinition interfaceImplType); + + // Same logic as other interface types above, but we also need a '[DynamicInterfaceCastableImplementation]' type and entry + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + externalTypeMapTargetType: proxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: trimTarget, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: trimTarget, + metadataTypeMapProxyType: proxyType.ToTypeSignature(), + interfaceTypeMapSourceType: trimTarget, + interfaceTypeMapProxyType: interfaceImplType.ToTypeSignature(), interopReferences: interopReferences, module: module); } /// - /// Creates a new custom attribute value for for a given custom-mapped type that is never marshalled or instantiated. + /// Creates a new custom attribute value for for the interface type. /// - /// The arguments for this invocation. - /// The runtime class name for Windows.UI.Xaml. - /// The runtime class name for Microsoft.UI.Xaml. - /// + /// The instance to use. + /// The module that the attribute will be used from. + /// Whether to use Windows.UI.Xaml projections. + private static void INotifyCollectionChangedInterfaceType( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections) + { + const string windowsUIXamlMetadata = "Windows.Foundation.UniversalApiContract"; + const string microsoftUIXamlMetadata = "Microsoft.UI.Xaml.WinUIContract"; + + TypeSignature trimTarget = interopReferences.INotifyCollectionChanged.ToReferenceTypeSignature(); + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; + + // Define the proxy type for the 'INotifyCollectionChanged' interface type + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + mappedType: trimTarget, + referenceType: null, + comWrappersMarshallerAttributeType: null, + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); + + // Define the 'InterfaceImpl' type for the 'INotifyCollectionChanged' interface type + INotifyCollectionChanged.InterfaceImpl( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: useWindowsUIXamlProjections, + interfaceImplType: out TypeDefinition interfaceImplType); + + // Same logic as other interface types above with '[DynamicInterfaceCastableImplementation]' + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + externalTypeMapTargetType: proxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: trimTarget, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: trimTarget, + metadataTypeMapProxyType: proxyType.ToTypeSignature(), + interfaceTypeMapSourceType: trimTarget, + interfaceTypeMapProxyType: interfaceImplType.ToTypeSignature(), + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a new custom attribute value for for the interface type. + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// Whether to use Windows.UI.Xaml projections. + private static void INotifyPropertyChangedInterfaceType( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections) + { + const string windowsUIXamlMetadata = "Windows.Foundation.UniversalApiContract"; + const string microsoftUIXamlMetadata = "Microsoft.UI.Xaml.WinUIContract"; + + TypeSignature trimTarget = interopReferences.INotifyPropertyChanged.ToReferenceTypeSignature(); + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; + + // Define the proxy type for the 'INotifyPropertyChanged' interface type + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + mappedType: trimTarget, + referenceType: null, + comWrappersMarshallerAttributeType: null, + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); + + // Define the 'InterfaceImpl' type for the 'INotifyPropertyChanged' interface type + INotifyPropertyChanged.InterfaceImpl( + interopReferences: interopReferences, + module: module, + useWindowsUIXamlProjections: useWindowsUIXamlProjections, + interfaceImplType: out TypeDefinition interfaceImplType); + + // Same logic as other interface types above with '[DynamicInterfaceCastableImplementation]' + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + externalTypeMapTargetType: proxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: trimTarget, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: trimTarget, + metadataTypeMapProxyType: proxyType.ToTypeSignature(), + interfaceTypeMapSourceType: trimTarget, + interfaceTypeMapProxyType: interfaceImplType.ToTypeSignature(), + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a new custom attribute value for for a given custom-mapped class type. + /// + /// The metadata name for Windows.UI.Xaml. + /// The metadata name for Microsoft.UI.Xaml. /// /// The instance to use. /// The module that the attribute will be used from. - private static void ManagedOnlyTypeOrInterface( - InteropGeneratorArgs args, - string windowsUIXamlTypeName, - string microsoftUIXamlTypeName, - TypeSignature target, + /// Whether to use Windows.UI.Xaml projections. + private static void ClassType( + string windowsUIXamlMetadata, + string microsoftUIXamlMetadata, TypeSignature trimTarget, InteropReferences interopReferences, - ModuleDefinition module) + ModuleDefinition module, + bool useWindowsUIXamlProjections) { - // This method is used for two kinds of custom-mapped types: - // - "Managed-only" types (such as 'PropertyChangedEventArgs'), which don't need CCW support, because they are - // marshalled by activating a fully native instance. Because of this, the proxy type for these types doesn't - // need the runtime class name annotation on them, which allows it to be defined in 'WinRT.Runtime.dll'. That - // in turn also allows the '[TypeMapAssociation]' attribute to be defined there. So here we - // only need the '[TypeMap]' attribute to handle untyped native to managed marshalling. - // - Interface types (such as 'IEnumerable'), which also don't need CCW support (because they are interfaces). - // For those, the IDIC attributes are in 'WinRT.Runtime.dll', so here we again only need the external type map. + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; + + // Define the proxy type for the class type. Same as above, we need to define this proxy type here, as the + // metadata type name is not fixed. We define a runtime class name so that 'TypeName' marshalling will be + // able to do lookups correctly (this attribute will be used, since the input type is a normal class type). + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(trimTarget, useWindowsUIXamlProjections), + metadataTypeName: null, + mappedType: trimTarget, + referenceType: null, + comWrappersMarshallerAttributeType: GetMarshallerAttributeType(trimTarget, interopReferences, module), + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); + + // This is similar to interfaces above, with the difference being that because class objects can be instantiated, + // the proxy type map used will only be with the marshalling type map group, and the metadata type map group is + // not needed here. Same goes for the external type map: we just have a normal entry for marshalling there. InteropTypeDefinitionBuilder.TypeMapAttributes( - runtimeClassName: args.UseWindowsUIXamlProjections ? windowsUIXamlTypeName : microsoftUIXamlTypeName, - externalTypeMapTargetType: target, + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(trimTarget, useWindowsUIXamlProjections), + metadataTypeName: null, + externalTypeMapTargetType: proxyType.ToTypeSignature(), externalTypeMapTrimTargetType: trimTarget, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: trimTarget, + marshallingTypeMapProxyType: proxyType.ToTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: null, interfaceTypeMapProxyType: null, interopReferences: interopReferences, @@ -139,53 +398,246 @@ private static void ManagedOnlyTypeOrInterface( } /// - /// Creates a new custom attribute value for for a given custom-mapped type that can be marshalled to native. + /// Creates a new custom attribute value for for a given custom-mapped delegate type. /// - /// The arguments for this invocation. - /// The runtime class name for Windows.UI.Xaml. - /// The runtime class name for Microsoft.UI.Xaml. + /// The metadata name for Windows.UI.Xaml. + /// The metadata name for Microsoft.UI.Xaml. /// /// The instance to use. /// The module that the attribute will be used from. - private static void WindowsRuntimeExposedType( - InteropGeneratorArgs args, - string windowsUIXamlTypeName, - string microsoftUIXamlTypeName, + /// Whether to use Windows.UI.Xaml projections. + private static void DelegateType( + string windowsUIXamlMetadata, + string microsoftUIXamlMetadata, TypeSignature trimTarget, InteropReferences interopReferences, - ModuleDefinition module) + ModuleDefinition module, + bool useWindowsUIXamlProjections) { - string runtimeClassName = args.UseWindowsUIXamlProjections ? windowsUIXamlTypeName : microsoftUIXamlTypeName; + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; - // Retrieve the '[ComWrappersMarshaller]' type from 'WinRT.Runtime.dll', which always follows this naming convention - TypeReference comWrappersMarshallerTypeReference = interopReferences.WindowsRuntimeModule.CreateTypeReference( + // Define the proxy type for the delegate type. Same as above, we need to define this proxy type here, as the + // metadata type name is not fixed. This type can be instantiated and boxed, so we need both possible names. + InteropTypeDefinitionBuilder.Proxy( ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), - name: (Utf8String)$"{trimTarget.Name}ComWrappersMarshallerAttribute"); + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(trimTarget, useWindowsUIXamlProjections), + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + mappedType: trimTarget, + referenceType: null, + comWrappersMarshallerAttributeType: GetMarshallerAttributeType(trimTarget, interopReferences, module), + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); - // The '[ComWrappersMarshaller]' type should always exist for all custom-mapped types, throw if it doesn't - if (comWrappersMarshallerTypeReference.Import(module).Resolve() is not TypeDefinition comWrappersMarshallerType) - { - throw WellKnownInteropExceptions.CustomMappedTypeComWrappersMarshallerAttributeTypeResolveError(comWrappersMarshallerTypeReference); - } + // Same as above for class types, the only difference here is in the proxy type definition for delegates + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(trimTarget, useWindowsUIXamlProjections), + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + externalTypeMapTargetType: proxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: trimTarget, + marshallingTypeMapSourceType: trimTarget, + marshallingTypeMapProxyType: proxyType.ToTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, + interfaceTypeMapSourceType: null, + interfaceTypeMapProxyType: null, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a new custom attribute value for for a given custom-mapped value type. + /// + /// The metadata name for Windows.UI.Xaml. + /// The metadata name for Microsoft.UI.Xaml. + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// Whether to use Windows.UI.Xaml projections. + private static void ValueType( + string windowsUIXamlMetadata, + string microsoftUIXamlMetadata, + TypeSignature trimTarget, + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections) + { + string metadata = useWindowsUIXamlProjections ? windowsUIXamlMetadata : microsoftUIXamlMetadata; - // Because these types can be instantiated and marshalled to native, but their runtime class name changes between 'Windows.UI.Xaml' and - // 'Microsoft.UI.Xaml', we also need to generate a proxy type for them, so that we can annotate it with '[WindowsRuntimeClassName]' with - // the correct runtime class name for the configuration actually being used at runtime by the current application or published library. + // Define the proxy type for the value type. In this case we still need both the runtime class name and the + // metadata type name, as above, but we also need to reference the boxed type instantiation for this type. InteropTypeDefinitionBuilder.Proxy( ns: InteropUtf8NameFactory.TypeNamespace(trimTarget), - name: trimTarget.Name!, + name: InteropUtf8NameFactory.TypeName(trimTarget), + mappedMetadata: metadata, + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(trimTarget, useWindowsUIXamlProjections), + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), mappedType: trimTarget, + referenceType: interopReferences.Nullable1.MakeGenericValueType(trimTarget), + comWrappersMarshallerAttributeType: GetMarshallerAttributeType(trimTarget, interopReferences, module), + interopReferences: interopReferences, + module: module, + proxyType: out TypeDefinition proxyType); + + // Same as above for delegate types, with both a marshalling and a metadata type map entry + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(trimTarget, useWindowsUIXamlProjections), + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(trimTarget, useWindowsUIXamlProjections), + externalTypeMapTargetType: proxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: trimTarget, + marshallingTypeMapSourceType: trimTarget, + marshallingTypeMapProxyType: proxyType.ToTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, + interfaceTypeMapSourceType: null, + interfaceTypeMapProxyType: null, + interopReferences: interopReferences, + module: module); + } + + /// + /// Creates a new custom attribute value for for IBindableVectorView. + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// Whether to use Windows.UI.Xaml projections. + private static void IBindableVectorViewType( + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections) + { + const string windowsUIXamlTypeName = "Windows.UI.Xaml.Interop.IBindableVectorView"; + const string microsoftUIXamlTypeName = "Microsoft.UI.Xaml.Interop.IBindableVectorView"; + + TypeSignature adapterType = interopReferences.BindableIReadOnlyListAdapter.ToReferenceTypeSignature(); + string runtimeClassName = useWindowsUIXamlProjections ? windowsUIXamlTypeName : microsoftUIXamlTypeName; + + // The 'BindableIReadOnlyListAdapter' type is a special type that is only used by the 'IBindableVector.GetView()' + // implementation (as it returns an 'IBindableVectorView' instance). This type is only used as a CCW. So we need + // a proxy type for it, with the correct runtime class name, and an entry just in the marshalling proxy type map. + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(adapterType), + name: InteropUtf8NameFactory.TypeName(adapterType), + mappedMetadata: null, runtimeClassName: runtimeClassName, + metadataTypeName: null, + mappedType: null, + referenceType: null, + comWrappersMarshallerAttributeType: GetMarshallerAttributeType(adapterType, interopReferences, module), + interopReferences: interopReferences, + module: module, + out TypeDefinition adapterProxyType); + + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: null, + metadataTypeName: null, + externalTypeMapTargetType: null, + externalTypeMapTrimTargetType: null, + marshallingTypeMapSourceType: adapterType, + marshallingTypeMapProxyType: adapterProxyType.ToTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, + interfaceTypeMapSourceType: null, + interfaceTypeMapProxyType: null, + interopReferences: interopReferences, + module: module); + + // Retrieve the '[IReadOnlyListComWrappersMarshallerAttribute]' type from 'WinRT.Runtime.dll', which is specialized + TypeReference comWrappersMarshallerTypeReference = interopReferences.WindowsRuntimeModule.CreateTypeReference( + ns: "ABI.System.Collections"u8, + name: "IReadOnlyListComWrappersMarshallerAttribute"u8); + + // Verify that this marshaller attribute does exist correctly and can be resolved + if (comWrappersMarshallerTypeReference.Resolve(module) is not TypeDefinition comWrappersMarshallerType) + { + throw WellKnownInteropExceptions.NonProjectedTypeComWrappersMarshallerAttributeTypeResolveError(comWrappersMarshallerTypeReference, "IBindableVectorView"); + } + + // Create the proxy type to support RCW marshalling as well + InteropTypeDefinitionBuilder.Proxy( + ns: "ABI.System.Collections"u8, + name: "<#corlib>IReadOnlyList", + mappedMetadata: null, + runtimeClassName: null, + metadataTypeName: null, + mappedType: null, + referenceType: null, comWrappersMarshallerAttributeType: comWrappersMarshallerType, interopReferences: interopReferences, module: module, - out TypeDefinition proxyType); + out TypeDefinition nativeObjectProxyType); - module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.TypeMapWindowsRuntimeComWrappersTypeMapGroup( - value: args.UseWindowsUIXamlProjections ? windowsUIXamlTypeName : microsoftUIXamlTypeName, - target: proxyType.ToTypeSignature(), - trimTarget: trimTarget, + // Define the type map entries. We only need one in the marshalling external type map. We can use 'IEnumerable' + // as the trim target for the specialized RCW type (since the 'IReadOnlyList' interface does not exist in .NET). + // This is also why we don't need to emit the '[WindowsRuntimeMappedMetadata]' attribute on the proxy type above. + InteropTypeDefinitionBuilder.TypeMapAttributes( + runtimeClassName: runtimeClassName, + metadataTypeName: null, + externalTypeMapTargetType: nativeObjectProxyType.ToTypeSignature(), + externalTypeMapTrimTargetType: interopReferences.IEnumerable.ToReferenceTypeSignature(), + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, + interfaceTypeMapSourceType: null, + interfaceTypeMapProxyType: null, interopReferences: interopReferences, - module: module)); + module: module); + } + + /// + /// Retrieves the marshaller attribute associated with a specified custom-mapped type. + /// + /// The custom-mapped type to retrieve the marshaller attribute for. + /// The instance to use. + /// The module that the attribute will be used from. + /// The marshaller attribute type for the input type. + /// Thrown if resolving the marshaller attribute type fails. + private static TypeDefinition GetMarshallerAttributeType( + TypeSignature type, + InteropReferences interopReferences, + ModuleDefinition module) + { + // Retrieve the '[ComWrappersMarshaller]' type from 'WinRT.Runtime.dll', which always follows this naming convention + TypeReference comWrappersMarshallerTypeReference = interopReferences.WindowsRuntimeModule.CreateTypeReference( + ns: InteropUtf8NameFactory.TypeNamespace(type), + name: (Utf8String)$"{type.Name}ComWrappersMarshallerAttribute"); + + // The '[ComWrappersMarshaller]' type should always exist for all custom-mapped types, throw if it doesn't + if (comWrappersMarshallerTypeReference.Resolve(module) is not TypeDefinition comWrappersMarshallerType) + { + throw WellKnownInteropExceptions.CustomMappedTypeComWrappersMarshallerAttributeTypeResolveError(type); + } + + return comWrappersMarshallerType; + } + + /// + /// Retrieves the "Methods" type associated with a specified custom-mapped type. + /// + /// The custom-mapped type to retrieve the "Methods" type for. + /// The instance to use. + /// The module that the attribute will be used from. + /// The "Methods" type for the input type. + /// Thrown if resolving the "Methods" type fails. + private static TypeDefinition GetMethodsType( + TypeSignature type, + InteropReferences interopReferences, + ModuleDefinition module) + { + // Retrieve the "Methods" type from 'WinRT.Runtime.dll', which always follows this naming convention + TypeReference methodsTypeReference = interopReferences.WindowsRuntimeModule.CreateTypeReference( + ns: InteropUtf8NameFactory.TypeNamespace(type), + name: (Utf8String)$"{type.Name}Methods"); + + // The "Methods" type should always exist for all custom-mapped types, throw if it doesn't + if (methodsTypeReference.Resolve(module) is not TypeDefinition methodsType) + { + throw WellKnownInteropExceptions.CustomMappedTypeMethodsTypeResolveError(type); + } + + return methodsType; } } \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs index e54d3ef6e..56e2103f1 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs @@ -917,6 +917,40 @@ public static void Marshaller( marshallerType.Methods.Add(unboxToUnmanagedMethod); } + /// + /// Creates a new type definition for the proxy type for some type. + /// + /// The for the type. + /// The instance returned by . + /// The instance to use. + /// The module that will contain the type being created. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting proxy type. + public static void Proxy( + TypeSignature delegateType, + TypeDefinition comWrappersMarshallerAttributeType, + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + out TypeDefinition proxyType) + { + // For delegate types, we need to both specify the mapped metadata name, so that when marshalling 'Type' instances to + // native we can correctly detect the mapped type to be a metadata type, and also annotate the proxy types with the + // '[WindowsRuntimeMetadataTypeName]', as that's different than the runtime class name (which uses 'IReference'). + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(delegateType), + name: InteropUtf8NameFactory.TypeName(delegateType), + mappedMetadata: "Windows.Foundation.FoundationContract", + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(delegateType, useWindowsUIXamlProjections), + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(delegateType, useWindowsUIXamlProjections), + mappedType: delegateType, + referenceType: null, + comWrappersMarshallerAttributeType: comWrappersMarshallerAttributeType, + interopReferences: interopReferences, + module: module, + out proxyType); + } + /// /// Creates the type map attributes for some type. /// @@ -926,18 +960,24 @@ public static void Marshaller( /// The module that will contain the type being created. /// Whether to use Windows.UI.Xaml projections. public static void TypeMapAttributes( - GenericInstanceTypeSignature delegateType, + TypeSignature delegateType, TypeDefinition proxyType, InteropReferences interopReferences, ModuleDefinition module, bool useWindowsUIXamlProjections) { + // For delegate types, we also need to pass the metadata type name when setting up the type map + // attributes, as we need '[TypeMap]' entries in the metadata type map as well. + // This allows marshalling a 'TypeName' representing a Windows Runtime delegate type correctly. InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(delegateType, useWindowsUIXamlProjections), + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(delegateType, useWindowsUIXamlProjections), externalTypeMapTargetType: proxyType.ToReferenceTypeSignature(), externalTypeMapTrimTargetType: delegateType, - proxyTypeMapSourceType: delegateType, - proxyTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + marshallingTypeMapSourceType: delegateType, + marshallingTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: null, interfaceTypeMapProxyType: null, interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.ICollectionKeyValuePair2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.ICollectionKeyValuePair2.cs index 6538beb70..fc09023c8 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.ICollectionKeyValuePair2.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.ICollectionKeyValuePair2.cs @@ -271,10 +271,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: null, + metadataTypeName: null, externalTypeMapTargetType: null, externalTypeMapTrimTargetType: null, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: collectionType, interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs index 62f44cf2e..7383d6fa1 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IList1.cs @@ -1091,10 +1091,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(listType, useWindowsUIXamlProjections), + metadataTypeName: null, externalTypeMapTargetType: proxyType.ToReferenceTypeSignature(), externalTypeMapTrimTargetType: listType, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: listType, + metadataTypeMapProxyType: proxyType.ToReferenceTypeSignature(), interfaceTypeMapSourceType: listType, interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, @@ -1108,10 +1111,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: null, + metadataTypeName: null, externalTypeMapTargetType: null, externalTypeMapTrimTargetType: null, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: interopReferences.ICollection1.MakeGenericReferenceType(elementType), interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyCollectionKeyValuePair2.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyCollectionKeyValuePair2.cs index 612b188b6..6f976dd83 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyCollectionKeyValuePair2.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyCollectionKeyValuePair2.cs @@ -136,10 +136,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: null, + metadataTypeName: null, externalTypeMapTargetType: null, externalTypeMapTrimTargetType: null, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: readOnlyCollectionType, interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs index a431d01a0..86b5ffc0e 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs @@ -472,10 +472,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(readOnlyListType, useWindowsUIXamlProjections), + metadataTypeName: null, externalTypeMapTargetType: proxyType.ToReferenceTypeSignature(), externalTypeMapTrimTargetType: readOnlyListType, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: readOnlyListType, + metadataTypeMapProxyType: proxyType.ToReferenceTypeSignature(), interfaceTypeMapSourceType: readOnlyListType, interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, @@ -490,10 +493,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: null, + metadataTypeName: null, externalTypeMapTargetType: null, externalTypeMapTrimTargetType: null, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: interopReferences.IReadOnlyCollection1.MakeGenericReferenceType(elementType), interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.KeyValuePair.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.KeyValuePair.cs index c126e227a..5dff8cadf 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.KeyValuePair.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.KeyValuePair.cs @@ -455,16 +455,50 @@ public static void ComWrappersMarshallerAttribute( marshallerAttributeType.Methods.Add(createObjectMethod); } + /// + /// Creates a new type definition for the proxy type of some type. + /// + /// The for the type. + /// The instance returned by . + /// The instance to use. + /// The module that will contain the type being created. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting proxy type. + public static void Proxy( + TypeSignature keyValuePairType, + TypeDefinition comWrappersMarshallerAttributeType, + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + out TypeDefinition proxyType) + { + // For 'KeyValuePair' types, we need to specify the mapped metadata name, so that when marshalling + // 'Type' instances to native we can correctly detect the mapped type to be a metadata type. We also need to + // reference the mapped type, so that we can retrieve the original 'Type' instance when marshalling from native. + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(keyValuePairType), + name: InteropUtf8NameFactory.TypeName(keyValuePairType), + mappedMetadata: "Windows.Foundation.FoundationContract", + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(keyValuePairType, useWindowsUIXamlProjections), + metadataTypeName: null, + mappedType: keyValuePairType, + referenceType: null, + comWrappersMarshallerAttributeType: comWrappersMarshallerAttributeType, + interopReferences: interopReferences, + module: module, + out proxyType); + } + /// /// Creates the type map attributes for some type. /// /// The for the type. - /// The instance returned by . + /// The instance returned by . /// The instance to use. /// The module that will contain the type being created. /// Whether to use Windows.UI.Xaml projections. public static void TypeMapAttributes( - GenericInstanceTypeSignature keyValuePairType, + TypeSignature keyValuePairType, TypeDefinition proxyType, InteropReferences interopReferences, ModuleDefinition module, @@ -472,10 +506,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(keyValuePairType, useWindowsUIXamlProjections), + metadataTypeName: null, externalTypeMapTargetType: proxyType.ToReferenceTypeSignature(), externalTypeMapTrimTargetType: keyValuePairType, - proxyTypeMapSourceType: keyValuePairType, - proxyTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + marshallingTypeMapSourceType: keyValuePairType, + marshallingTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: null, interfaceTypeMapProxyType: null, interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs index f15c0dd29..6a9a84bb4 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.SzArray.cs @@ -527,11 +527,46 @@ public static void ComWrappersMarshallerAttribute( marshallerType.Methods.Add(createObjectMethod); } + /// + /// Creates a new type definition for the proxy type for some SZ array type. + /// + /// The for the SZ array type. + /// The instance for the marshaller attribute type. + /// The instance to use. + /// The module that will contain the type being created. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting proxy type. + public static void Proxy( + SzArrayTypeSignature arrayType, + TypeDefinition comWrappersMarshallerAttributeType, + InteropReferences interopReferences, + ModuleDefinition module, + bool useWindowsUIXamlProjections, + out TypeDefinition proxyType) + { + // This is a proxy for Windows Runtime arrays, so we also need to emit the '[WindowsRuntimeMappedMetadata]' + // attribute, so that during 'TypeName' marshalling we can detect whether the type is a metadata type. Note + // that arrays with element types that are not Windows Runtime types will still have entries in the marshalling + // type map (as they're treated the same as normal user-defined types), so this allows us to distinguish them. + InteropTypeDefinitionBuilder.Proxy( + ns: InteropUtf8NameFactory.TypeNamespace(arrayType), + name: InteropUtf8NameFactory.TypeName(arrayType), + mappedMetadata: "Windows.Foundation.FoundationContract", + runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(arrayType, useWindowsUIXamlProjections), + metadataTypeName: null, + mappedType: arrayType, + referenceType: null, + comWrappersMarshallerAttributeType: comWrappersMarshallerAttributeType, + interopReferences: interopReferences, + module: module, + proxyType: out proxyType); + } + /// /// Creates the type map attributes for some SZ array type. /// /// The for the SZ array type. - /// The instance returned by . + /// The instance returned by . /// The instance to use. /// Whether to use Windows.UI.Xaml projections. /// The module that will contain the type being created. @@ -544,10 +579,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(arrayType, useWindowsUIXamlProjections), + metadataTypeName: null, externalTypeMapTargetType: proxyType.ToReferenceTypeSignature(), externalTypeMapTrimTargetType: arrayType, - proxyTypeMapSourceType: arrayType, - proxyTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + marshallingTypeMapSourceType: arrayType, + marshallingTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: null, interfaceTypeMapProxyType: null, interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.UserDefinedType.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.UserDefinedType.cs index 08585b05f..975326f97 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.UserDefinedType.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.UserDefinedType.cs @@ -270,8 +270,11 @@ public static void Proxy( InteropTypeDefinitionBuilder.Proxy( ns: InteropUtf8NameFactory.TypeNamespace(userDefinedType), name: InteropUtf8NameFactory.TypeName(userDefinedType), - mappedType: userDefinedType, + mappedMetadata: null, runtimeClassName: null, + metadataTypeName: null, + mappedType: userDefinedType, + referenceType: null, comWrappersMarshallerAttributeType: comWrappersMarshallerAttributeType, interopReferences: interopReferences, module: module, @@ -294,8 +297,11 @@ public static void Proxy( InteropTypeDefinitionBuilder.Proxy( ns: InteropUtf8NameFactory.TypeNamespace(userDefinedType), name: InteropUtf8NameFactory.TypeName(userDefinedType), - mappedType: userDefinedType, + mappedMetadata: null, runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(interfaceType, useWindowsUIXamlProjections), + metadataTypeName: null, + mappedType: null, + referenceType: null, comWrappersMarshallerAttributeType: comWrappersMarshallerAttributeType, interopReferences: interopReferences, module: module, @@ -318,10 +324,13 @@ public static void TypeMapAttributes( { InteropTypeDefinitionBuilder.TypeMapAttributes( runtimeClassName: null, + metadataTypeName: null, externalTypeMapTargetType: null, externalTypeMapTrimTargetType: null, - proxyTypeMapSourceType: userDefinedType, - proxyTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + marshallingTypeMapSourceType: userDefinedType, + marshallingTypeMapProxyType: proxyType.ToReferenceTypeSignature(), + metadataTypeMapSourceType: null, + metadataTypeMapProxyType: null, interfaceTypeMapSourceType: null, interfaceTypeMapProxyType: null, interopReferences: interopReferences, diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs index 5cf712626..3870dcb68 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.cs @@ -708,27 +708,35 @@ private static void InterfaceEntriesImpl( } /// - /// Creates a new type definition for the proxy type of some managed type. + /// Creates a new type definition for the proxy type of some interface type. /// - /// The for the mapped type the proxy type is for. + /// The for the mapped type the proxy type is for. /// The instance for the marshaller attribute type. /// The instance to use. /// The module that will contain the type being created. /// Whether to use Windows.UI.Xaml projections. /// The resulting proxy type. public static void Proxy( - TypeSignature mappedType, + TypeSignature interfaceType, TypeDefinition comWrappersMarshallerAttributeType, InteropReferences interopReferences, ModuleDefinition module, bool useWindowsUIXamlProjections, out TypeDefinition proxyType) { + // This method is only used with interface types. Because of this, we need also emit the + // '[WindowsRuntimeMappedType]' attribute, so that 'TypeName' marshalling can retrieve + // the proxy type containing the runtime class name from the input managed type. We also + // emit '[WindowsRuntimeMetadataTypeName]', to support mapping the generic interface name + // when marshalling 'TypeName' instances. Nobody would need a runtime class name here. Proxy( - ns: InteropUtf8NameFactory.TypeNamespace(mappedType), - name: InteropUtf8NameFactory.TypeName(mappedType), - mappedType: mappedType, - runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(mappedType, useWindowsUIXamlProjections), + ns: InteropUtf8NameFactory.TypeNamespace(interfaceType), + name: InteropUtf8NameFactory.TypeName(interfaceType), + mappedMetadata: null, + runtimeClassName: null, + metadataTypeName: MetadataTypeNameGenerator.GetMetadataTypeName(interfaceType, useWindowsUIXamlProjections), + mappedType: interfaceType, + referenceType: null, comWrappersMarshallerAttributeType: comWrappersMarshallerAttributeType, interopReferences: interopReferences, module: module, @@ -740,18 +748,24 @@ public static void Proxy( /// /// The namespace for the type. /// The type name. - /// The for the mapped type the proxy type is for. - /// The runtime class name for the managed type (if null, the source type will be used). - /// The instance for the marshaller attribute type. + /// The name of the mapped metadata for the proxy type (if , the attribute will be omitted). + /// The runtime class name for the managed type (if , the attribute will be omitted). + /// The metadata type name for the managed type (if , the attribute will be omitted). + /// The for the mapped type the proxy type is for (if , the attribute will be omitted). + /// The for the reference type the proxy type is associated with (if , the attribute will be omitted). + /// The instance for the marshaller attribute type (if , the attribute will be omitted). /// The instance to use. /// The module that will contain the type being created. /// The resulting proxy type. public static void Proxy( Utf8String ns, Utf8String name, - TypeSignature mappedType, + string? mappedMetadata, string? runtimeClassName, - TypeDefinition comWrappersMarshallerAttributeType, + string? metadataTypeName, + TypeSignature? mappedType, + TypeSignature? referenceType, + TypeDefinition? comWrappersMarshallerAttributeType, InteropReferences interopReferences, ModuleDefinition module, out TypeDefinition proxyType) @@ -765,19 +779,40 @@ public static void Proxy( module.TopLevelTypes.Add(proxyType); + // Add the '[WindowsRuntimeMappedMetadata]' attribute with the provided .winmd name, if available + if (mappedMetadata is not null) + { + proxyType.CustomAttributes.Add(new CustomAttribute( + constructor: interopReferences.WindowsRuntimeMappedMetadataAttribute_ctor.Import(module), + signature: new CustomAttributeSignature(new CustomAttributeArgument( + argumentType: module.CorLibTypeFactory.String, + value: mappedMetadata)))); + } + + // Add the '[WindowsRuntimeClassName]' attribute with the provided runtime class name, if available if (runtimeClassName is not null) { - // Add the '[WindowsRuntimeClassName]' attribute with the provided runtime class name proxyType.CustomAttributes.Add(new CustomAttribute( constructor: interopReferences.WindowsRuntimeClassNameAttribute_ctor.Import(module), signature: new CustomAttributeSignature(new CustomAttributeArgument( argumentType: module.CorLibTypeFactory.String, value: runtimeClassName)))); } - else + + // Add the '[WindowsRuntimeMetadataTypeName]' attribute with the provided metadata type name, if available + if (metadataTypeName is not null) + { + proxyType.CustomAttributes.Add(new CustomAttribute( + constructor: interopReferences.WindowsRuntimeMetadataTypeNameAttribute_ctor.Import(module), + signature: new CustomAttributeSignature(new CustomAttributeArgument( + argumentType: module.CorLibTypeFactory.String, + value: metadataTypeName)))); + } + + // Add the '[WindowsRuntimeMappedType]' attribute with the provided mapped type, if available. + // This allows retrieving the user-provided runtime class name from the original managed type. + if (mappedType is not null) { - // Add the '[WindowsRuntimeMappedType]' attribute with the provided mapped type. This allows - // the runtime to retrieve the user-provided runtime class name from the original type. proxyType.CustomAttributes.Add(new CustomAttribute( constructor: interopReferences.WindowsRuntimeMappedTypeAttribute_ctor.Import(module), signature: new CustomAttributeSignature(new CustomAttributeArgument( @@ -785,8 +820,22 @@ public static void Proxy( value: mappedType.Import(module))))); } - // Add the generated marshaller attribute - proxyType.CustomAttributes.Add(new CustomAttribute(comWrappersMarshallerAttributeType.GetConstructor()!.Import(module))); + // Add the '[WindowsRuntimeReferenceType]' attribute with the provided reference type, if available. + // This allows retrieving the boxed type (i.e. a 'Nullable' instantiation) for a given value type. + if (referenceType is not null) + { + proxyType.CustomAttributes.Add(new CustomAttribute( + constructor: interopReferences.WindowsRuntimeReferenceTypeAttribute_ctor.Import(module), + signature: new CustomAttributeSignature(new CustomAttributeArgument( + argumentType: interopReferences.Type.Import(module).ToReferenceTypeSignature(), + value: referenceType.Import(module))))); + } + + // Add the generated marshaller attribute, if available + if (comWrappersMarshallerAttributeType is not null) + { + proxyType.CustomAttributes.Add(new CustomAttribute(comWrappersMarshallerAttributeType.GetConstructor()!.Import(module))); + } } /// @@ -808,10 +857,13 @@ public static void TypeMapAttributes( { TypeMapAttributes( runtimeClassName: RuntimeClassNameGenerator.GetRuntimeClassName(interfaceType, useWindowsUIXamlProjections), + metadataTypeName: null, externalTypeMapTargetType: proxyType.ToReferenceTypeSignature(), externalTypeMapTrimTargetType: interfaceType, - proxyTypeMapSourceType: null, - proxyTypeMapProxyType: null, + marshallingTypeMapSourceType: null, + marshallingTypeMapProxyType: null, + metadataTypeMapSourceType: interfaceType, + metadataTypeMapProxyType: proxyType.ToReferenceTypeSignature(), interfaceTypeMapSourceType: interfaceType, interfaceTypeMapProxyType: interfaceImplType.ToReferenceTypeSignature(), interopReferences: interopReferences, @@ -821,28 +873,34 @@ public static void TypeMapAttributes( /// /// Creates the type map attributes for a given type. /// - /// The runtime class name for the managed type. + /// The runtime class name for the managed type (if , the attribute will be omitted). + /// The metadata type name for the managed type (if , the attribute will be omitted). /// The target type for . /// The trim target type for . - /// The source type for . - /// The proxy type for . + /// The source type for . + /// The proxy type for . + /// The source type for . + /// The proxy type for . /// The IDIC source type for . /// The IDIC proxy type for . /// The instance to use. /// The module that will contain the type being created. public static void TypeMapAttributes( string? runtimeClassName, + string? metadataTypeName, [NotNullIfNotNull(nameof(runtimeClassName))] TypeSignature? externalTypeMapTargetType, [NotNullIfNotNull(nameof(runtimeClassName))] TypeSignature? externalTypeMapTrimTargetType, - [NotNullIfNotNull(nameof(proxyTypeMapProxyType))] TypeSignature? proxyTypeMapSourceType, - [NotNullIfNotNull(nameof(proxyTypeMapSourceType))] TypeSignature? proxyTypeMapProxyType, + [NotNullIfNotNull(nameof(marshallingTypeMapProxyType))] TypeSignature? marshallingTypeMapSourceType, + [NotNullIfNotNull(nameof(marshallingTypeMapSourceType))] TypeSignature? marshallingTypeMapProxyType, + [NotNullIfNotNull(nameof(metadataTypeMapProxyType))] TypeSignature? metadataTypeMapSourceType, + [NotNullIfNotNull(nameof(metadataTypeMapSourceType))] TypeSignature? metadataTypeMapProxyType, [NotNullIfNotNull(nameof(interfaceTypeMapProxyType))] TypeSignature? interfaceTypeMapSourceType, [NotNullIfNotNull(nameof(interfaceTypeMapSourceType))] TypeSignature? interfaceTypeMapProxyType, InteropReferences interopReferences, ModuleDefinition module) { // Emit the '[TypeMap]' attribute for the external type map. - // This is optional, only needed for projected types. + // This is optional, only needed for custom-mapped or projected types. if (runtimeClassName is not null) { module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.TypeMapWindowsRuntimeComWrappersTypeMapGroup( @@ -853,13 +911,36 @@ public static void TypeMapAttributes( module: module)); } + // Emit the '[TypeMap]' attribute for the metadata type map. + // This is also optional, only needed for some 'TypeName' marshalling cases. + if (metadataTypeName is not null) + { + module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.TypeMapWindowsRuntimeMetadataTypeMapGroup( + value: metadataTypeName, + target: externalTypeMapTargetType!, + trimTarget: externalTypeMapTrimTargetType!, + interopReferences: interopReferences, + module: module)); + } + // Emit the '[TypeMapAssociation]' attribute for the proxy type map. - // This is only needed for types that can actually be instantiated. - if (proxyTypeMapSourceType is not null) + // This is only needed for types that can actually be instantiated (e.g. classes). + if (marshallingTypeMapSourceType is not null) { module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.TypeMapAssociationWindowsRuntimeComWrappersTypeMapGroup( - source: proxyTypeMapSourceType, - proxy: proxyTypeMapProxyType!, + source: marshallingTypeMapSourceType, + proxy: marshallingTypeMapProxyType!, + interopReferences: interopReferences, + module: module)); + } + + // Emit the '[TypeMapAssociation]' attribute for the metadata type map. + // This is not always needed, but it is for types that cannot actually be instantiated. + if (metadataTypeMapSourceType is not null) + { + module.Assembly!.CustomAttributes.Add(InteropCustomAttributeFactory.TypeMapAssociationWindowsRuntimeMetadataTypeMapGroup( + source: metadataTypeMapSourceType, + proxy: metadataTypeMapProxyType!, interopReferences: interopReferences, module: module)); } diff --git a/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs b/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs index ada994168..4ee1d7453 100644 --- a/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs +++ b/src/WinRT.Interop.Generator/Errors/WellKnownInteropExceptions.cs @@ -425,7 +425,7 @@ public static WellKnownInteropException DynamicDynamicCustomMappedTypeMapEntries /// /// Failed to resolve the associated ComWrappersMarshallerAttribute type for a custom-mapped type. /// - public static WellKnownInteropException CustomMappedTypeComWrappersMarshallerAttributeTypeResolveError(TypeReference type) + public static WellKnownInteropException CustomMappedTypeComWrappersMarshallerAttributeTypeResolveError(TypeSignature type) { return Exception(48, $"Failed to resolve the associated 'ComWrappersMarshallerAttribute' type for the custom-mapped type '{type}'."); } @@ -674,6 +674,30 @@ public static WellKnownInteropException MethodFixupError(InteropMethodFixup fixu return Exception(78, $"Failed to apply fixup '{fixup.GetType()}' to method '{method}'.", exception); } + /// + /// Failed to generate the runtime class name of some Windows Runtime type. + /// + public static Exception RuntimeClassNameGenerationError(TypeSignature type) + { + return Exception(79, $"Failed to generate the runtime class name for type '{type}'."); + } + + /// + /// Failed to resolve the target ComWrappersMarshallerAttribute type for a non-projected Windows Runtime type. + /// + public static WellKnownInteropException NonProjectedTypeComWrappersMarshallerAttributeTypeResolveError(TypeReference attributeType, string nativeType) + { + return Exception(80, $"Failed to resolve the 'ComWrappersMarshallerAttribute' type '{attributeType}' for a non-projected Windows Runtime type '{nativeType}'."); + } + + /// + /// Failed to resolve the associated "Methods" type for a custom-mapped type. + /// + public static WellKnownInteropException CustomMappedTypeMethodsTypeResolveError(TypeSignature type) + { + return Exception(81, $"Failed to resolve the associated 'Methods' type for the custom-mapped type '{type}'."); + } + /// /// Creates a new exception with the specified id and message. /// diff --git a/src/WinRT.Interop.Generator/Extensions/TypeSignatureExtensions.cs b/src/WinRT.Interop.Generator/Extensions/TypeSignatureExtensions.cs index eb1cdfa5a..83d20d61b 100644 --- a/src/WinRT.Interop.Generator/Extensions/TypeSignatureExtensions.cs +++ b/src/WinRT.Interop.Generator/Extensions/TypeSignatureExtensions.cs @@ -16,6 +16,11 @@ internal static class TypeSignatureExtensions { extension(TypeSignature signature) { + /// + /// Gets whether the current type is a (constructed) generic type. + /// + public bool IsGenericType => signature.ElementType is ElementType.GenericInst; + /// /// Determines whether the current type is assignable from the provided type. /// diff --git a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs index 4797b9a17..43cac0eb8 100644 --- a/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs +++ b/src/WinRT.Interop.Generator/Extensions/WindowsRuntimeExtensions.cs @@ -162,6 +162,7 @@ public bool IsCustomMappedWindowsRuntimeNonGenericStructOrClassType(InteropRefer SignatureComparer.IgnoreVersion.Equals(type, interopReferences.Vector4) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.DataErrorsChangedEventArgs) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.PropertyChangedEventArgs) || + SignatureComparer.IgnoreVersion.Equals(type, interopReferences.NotifyCollectionChangedAction) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.NotifyCollectionChangedEventArgs); } @@ -178,6 +179,7 @@ public bool IsManuallyProjectedWindowsRuntimeNonGenericStructOrClassType(Interop return SignatureComparer.IgnoreVersion.Equals(type, interopReferences.CollectionChange) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.AsyncStatus) || + SignatureComparer.IgnoreVersion.Equals(type, interopReferences.PropertyType) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.Point) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.Rect) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.Size) || @@ -245,7 +247,8 @@ public bool IsManuallyProjectedWindowsRuntimeNonGenericInterfaceType(InteropRefe return SignatureComparer.IgnoreVersion.Equals(type, interopReferences.IAsyncAction) || SignatureComparer.IgnoreVersion.Equals(type, interopReferences.IAsyncInfo) || - SignatureComparer.IgnoreVersion.Equals(type, interopReferences.IVectorChangedEventArgs); + SignatureComparer.IgnoreVersion.Equals(type, interopReferences.IVectorChangedEventArgs) || + SignatureComparer.IgnoreVersion.Equals(type, interopReferences.IStringable); } /// diff --git a/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs b/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs index 3ab118710..c00cdbee5 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropCustomAttributeFactory.cs @@ -227,6 +227,65 @@ public static CustomAttribute TypeMapAssociationWindowsRuntimeComWrappersTypeMap value: proxy.Import(module))])); } + /// + /// Creates a new custom attribute value for (and imports all metadata elements for it). + /// + /// + /// + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// The resulting instance. + public static CustomAttribute TypeMapWindowsRuntimeMetadataTypeMapGroup( + string value, + TypeSignature target, + TypeSignature trimTarget, + InteropReferences interopReferences, + ModuleDefinition module) + { + // Create the following attribute: + // + // [TypeMap(, , )] + return new(interopReferences.TypeMapAttributeWindowsRuntimeMetadataTypeMapGroup_ctor_TrimTarget.Import(module), new CustomAttributeSignature( + fixedArguments: [ + new CustomAttributeArgument( + argumentType: module.CorLibTypeFactory.String, + value: value), + new CustomAttributeArgument( + argumentType: interopReferences.Type.Import(module).ToReferenceTypeSignature(), + value: target.Import(module)), + new CustomAttributeArgument( + argumentType: interopReferences.Type.Import(module).ToReferenceTypeSignature(), + value: trimTarget.Import(module))])); + } + + /// + /// Creates a new custom attribute value for (and imports all metadata elements for it). + /// + /// + /// + /// The instance to use. + /// The module that the attribute will be used from. + /// The resulting instance. + public static CustomAttribute TypeMapAssociationWindowsRuntimeMetadataTypeMapGroup( + TypeSignature source, + TypeSignature proxy, + InteropReferences interopReferences, + ModuleDefinition module) + { + // Create the following attribute: + // + // [TypeMap(, )] + return new(interopReferences.TypeMapAssociationAttributeWindowsRuntimeMetadataTypeMapGroup_ctor.Import(module), new CustomAttributeSignature( + fixedArguments: [ + new CustomAttributeArgument( + argumentType: interopReferences.Type.Import(module).ToReferenceTypeSignature(), + value: source.Import(module)), + new CustomAttributeArgument( + argumentType: interopReferences.Type.Import(module).ToReferenceTypeSignature(), + value: proxy.Import(module))])); + } + /// /// Creates a new custom attribute value for (and imports all metadata elements for it). /// diff --git a/src/WinRT.Interop.Generator/Factories/WellKnownCilMethodBodyFactory.cs b/src/WinRT.Interop.Generator/Factories/WellKnownCilMethodBodyFactory.cs index 6bf67720c..bb42161a5 100644 --- a/src/WinRT.Interop.Generator/Factories/WellKnownCilMethodBodyFactory.cs +++ b/src/WinRT.Interop.Generator/Factories/WellKnownCilMethodBodyFactory.cs @@ -61,7 +61,7 @@ public static CilMethodBody DynamicInterfaceCastableImplementation( } // Call the forwarded method and return - body.Instructions.Add(new CilInstruction(Call, forwardedMethod)); + body.Instructions.Add(new CilInstruction(Call, forwardedMethod.Import(module))); body.Instructions.Add(new CilInstruction(Ret)); return body; @@ -129,7 +129,7 @@ public static CilMethodBody DynamicInterfaceCastableImplementation( // (interfaceReference, ); { Ldloc_1 }, { nop_type1Args }, - { Call, forwardedMethod1 }, + { Call, forwardedMethod1.Import(module) }, { Ret }, // interfaceReference = thisObject.GetObjectReferenceForInterface(typeof()); @@ -143,7 +143,7 @@ public static CilMethodBody DynamicInterfaceCastableImplementation( // (interfaceReference, ); { Ldloc_1 }, { nop_type2Args }, - { Call, forwardedMethod2 }, + { Call, forwardedMethod2.Import(module) }, { Ret } } }; @@ -219,7 +219,7 @@ public static CilMethodBody DynamicInterfaceCastableImplementation( // (thisObject, thisReference).(value); { Ldloc_0 }, { Ldloc_1 }, - { Call, eventMethod }, + { Call, eventMethod.Import(module) }, { Ldarg_1 }, { Callvirt, accessorMethod.Import(module) }, { Ret } diff --git a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs index d65e6bef4..ff309c5b8 100644 --- a/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs +++ b/src/WinRT.Interop.Generator/Generation/InteropGenerator.Emit.cs @@ -364,8 +364,8 @@ private static void DefineGenericDelegateTypes( module: module, out TypeDefinition delegateComWrappersMarshallerType); - InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + InteropTypeDefinitionBuilder.Delegate.Proxy( + delegateType: typeSignature, comWrappersMarshallerAttributeType: delegateComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -530,7 +530,7 @@ private static void DefineIEnumeratorTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: enumeratorComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -656,7 +656,7 @@ private static void DefineIEnumerableTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: enumerableComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -785,7 +785,7 @@ private static void DefineIReadOnlyListTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: readOnlyListComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -922,7 +922,7 @@ private static void DefineIListTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: listComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1051,7 +1051,7 @@ private static void DefineIReadOnlyDictionaryTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: readOnlyDictionaryComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1188,7 +1188,7 @@ private static void DefineIDictionaryTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: dictionaryComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1304,8 +1304,8 @@ private static void DefineKeyValuePairTypes( module: module, marshallerAttributeType: out TypeDefinition marshallerAttributeType); - InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + InteropTypeDefinitionBuilder.KeyValuePair.Proxy( + keyValuePairType: typeSignature, comWrappersMarshallerAttributeType: marshallerAttributeType, interopReferences: interopReferences, module: module, @@ -1415,7 +1415,7 @@ private static void DefineIMapChangedEventArgsTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: argsComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1536,7 +1536,7 @@ private static void DefineIObservableVectorTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: comWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1657,7 +1657,7 @@ private static void DefineIObservableMapTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: comWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1768,7 +1768,7 @@ private static void DefineIAsyncActionWithProgressTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: actionComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1879,7 +1879,7 @@ private static void DefineIAsyncOperationTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: operationComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -1990,7 +1990,7 @@ private static void DefineIAsyncOperationWithProgressTypes( interfaceImplType: out TypeDefinition interfaceImplType); InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + interfaceType: typeSignature, comWrappersMarshallerAttributeType: operationComWrappersMarshallerType, interopReferences: interopReferences, module: module, @@ -2200,8 +2200,8 @@ private static void DefineSzArrayTypes( module: module, out TypeDefinition arrayComWrappersMarshallerType); - InteropTypeDefinitionBuilder.Proxy( - mappedType: typeSignature, + InteropTypeDefinitionBuilder.SzArray.Proxy( + arrayType: typeSignature, comWrappersMarshallerAttributeType: arrayComWrappersMarshallerType, interopReferences: interopReferences, module: module, diff --git a/src/WinRT.Interop.Generator/Helpers/MetadataTypeNameGenerator.cs b/src/WinRT.Interop.Generator/Helpers/MetadataTypeNameGenerator.cs new file mode 100644 index 000000000..59a83dae6 --- /dev/null +++ b/src/WinRT.Interop.Generator/Helpers/MetadataTypeNameGenerator.cs @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Runtime.CompilerServices; +using AsmResolver.DotNet.Signatures; + +namespace WindowsRuntime.InteropGenerator.Helpers; + +/// +/// A generator for metadata type names of Windows Runtime types. +/// +internal static class MetadataTypeNameGenerator +{ + /// + /// Generates the Windows Runtime metadata type name for a (potentially generic) type, + /// applying known type-name mappings and recursively formatting generic arguments. + /// + /// The to generate the Windows Runtime metadata type name for. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting Windows Runtime metadata type name for . + public static string GetMetadataTypeName(TypeSignature type, bool useWindowsUIXamlProjections) + { + DefaultInterpolatedStringHandler handler = new(0, 0, null, stackalloc char[256]); + + AppendMetadataTypeName(ref handler, type, useWindowsUIXamlProjections); + + return handler.ToStringAndClear(); + } + + /// + /// Appends the Windows Runtime metadata type name for a (potentially generic) type, + /// applying known type-name mappings and recursively formatting generic arguments. + /// + /// The value to append to. + /// The to generate the Windows Runtime metadata type name for. + /// Whether to use Windows.UI.Xaml projections. + /// The resulting Windows Runtime metadata type name for . + public static void AppendMetadataTypeName( + ref DefaultInterpolatedStringHandler interpolatedStringHandler, + TypeSignature type, + bool useWindowsUIXamlProjections) + { + // Handle SZ array types and map them to 'IReferenceArray' type names + if (type is SzArrayTypeSignature szArrayTypeSignature) + { + interpolatedStringHandler.AppendLiteral("Windows.Foundation.IReferenceArray`1<"); + + AppendMetadataTypeName(ref interpolatedStringHandler, szArrayTypeSignature.BaseType, useWindowsUIXamlProjections); + + interpolatedStringHandler.AppendLiteral(">"); + } + else if (type is GenericInstanceTypeSignature genericInstanceTypeSignature) + { + // For constructed generic types, we first format the generic type (with a mapped + // name, if applicable), and then recursively process all generic type arguments. + if (TypeMapping.TryFindMappedTypeName(genericInstanceTypeSignature.GenericType.FullName, useWindowsUIXamlProjections, out string? mappedTypeName)) + { + interpolatedStringHandler.AppendLiteral(mappedTypeName); + } + else + { + interpolatedStringHandler.AppendLiteral(genericInstanceTypeSignature.GenericType.FullName); + } + + interpolatedStringHandler.AppendLiteral("<"); + + // Recursively format each type argument + for (int i = 0; i < genericInstanceTypeSignature.TypeArguments.Count; i++) + { + // Add the ', ' separator after the first type argument + if (i > 0) + { + interpolatedStringHandler.AppendLiteral(", "); + } + + AppendMetadataTypeName(ref interpolatedStringHandler, genericInstanceTypeSignature.TypeArguments[i], useWindowsUIXamlProjections); + } + + interpolatedStringHandler.AppendLiteral(">"); + } + else if (TypeMapping.TryFindMappedTypeName(type.FullName, useWindowsUIXamlProjections, out string? simpleMappedTypeName)) + { + // We have a simple, non-generic type, so format its mapped type if available + interpolatedStringHandler.AppendLiteral(simpleMappedTypeName); + } + else + { + // Otherwise the type must be a projected type, so just format the full name + interpolatedStringHandler.AppendLiteral(type.FullName); + } + } +} diff --git a/src/WinRT.Interop.Generator/Helpers/RuntimeClassNameGenerator.cs b/src/WinRT.Interop.Generator/Helpers/RuntimeClassNameGenerator.cs index a586814cc..9050c1898 100644 --- a/src/WinRT.Interop.Generator/Helpers/RuntimeClassNameGenerator.cs +++ b/src/WinRT.Interop.Generator/Helpers/RuntimeClassNameGenerator.cs @@ -2,7 +2,9 @@ // Licensed under the MIT License. using System.Runtime.CompilerServices; +using AsmResolver.DotNet; using AsmResolver.DotNet.Signatures; +using WindowsRuntime.InteropGenerator.Errors; namespace WindowsRuntime.InteropGenerator.Helpers; @@ -22,64 +24,36 @@ public static string GetRuntimeClassName(TypeSignature type, bool useWindowsUIXa { DefaultInterpolatedStringHandler handler = new(0, 0, null, stackalloc char[256]); - // Helper to format a full type signature into a target interpolated handler - static void AppendRuntimeClassName( - ref DefaultInterpolatedStringHandler interpolatedStringHandler, - TypeSignature type, - bool useWindowsUIXamlProjections) + // We need to be able to resolve the type definition to determine whether we need + // to wrap the metadata type name within "IReference`1<...>" (e.g. for delegates). + if (type.Resolve() is not TypeDefinition typeDefinition) { - // Handle SZ array types and map them to 'IReferenceArray' type names - if (type is SzArrayTypeSignature szArrayTypeSignature) - { - interpolatedStringHandler.AppendLiteral("Windows.Foundation.IReferenceArray`1<"); - - AppendRuntimeClassName(ref interpolatedStringHandler, szArrayTypeSignature.BaseType, useWindowsUIXamlProjections); + throw WellKnownInteropExceptions.RuntimeClassNameGenerationError(type); + } - interpolatedStringHandler.AppendLiteral(">"); - } - else if (type is GenericInstanceTypeSignature genericInstanceTypeSignature) - { - // For constructed generic types, we first format the generic type (with a mapped - // name, if applicable), and then recursively process all generic type arguments. - if (TypeMapping.TryFindMappedTypeName(genericInstanceTypeSignature.GenericType.FullName, useWindowsUIXamlProjections, out string? mappedTypeName)) - { - interpolatedStringHandler.AppendLiteral(mappedTypeName); - } - else - { - interpolatedStringHandler.AppendLiteral(genericInstanceTypeSignature.GenericType.FullName); - } + // We need to wrap the metadata name with "IReference`1<...>" only for non-generic value types, and for delegate + // types. We skip generic value types because the only possible type is 'KeyValuePair', but that is + // a Windows Runtime interface. We also need to make sure to skip SZ arrays manually. Note that when resolving the + // signature of an SZ array type, we'd just get a definition for the array element type. So we need to manually + // check for that scenario via the original type signature directly to make sure to not accidentally mark arrays + // of some type that would require reference support, as needing reference support themselves. + bool isReference = type is not SzArrayTypeSignature && ((type.IsValueType && !type.IsGenericType) || typeDefinition.IsDelegate); - interpolatedStringHandler.AppendLiteral("<"); + if (isReference) + { + handler.AppendLiteral("Windows.Foundation.IReference`1<"); + } - // Recursively format each type argument - for (int i = 0; i < genericInstanceTypeSignature.TypeArguments.Count; i++) - { - // Add the ', ' separator after the first type argument - if (i > 0) - { - interpolatedStringHandler.AppendLiteral(", "); - } + // Aside from the possible "IReference`1<...>" prefix, the runtime class name will be the same + // as the metadata type name for all cases, so here we just forward to that to generate it. + MetadataTypeNameGenerator.AppendMetadataTypeName(ref handler, type, useWindowsUIXamlProjections); - AppendRuntimeClassName(ref interpolatedStringHandler, genericInstanceTypeSignature.TypeArguments[i], useWindowsUIXamlProjections); - } + if (isReference) + { + handler.AppendLiteral(">"); - interpolatedStringHandler.AppendLiteral(">"); - } - else if (TypeMapping.TryFindMappedTypeName(type.FullName, useWindowsUIXamlProjections, out string? simpleMappedTypeName)) - { - // We have a simple, non-generic type, so format its mapped type if available - interpolatedStringHandler.AppendLiteral(simpleMappedTypeName); - } - else - { - // Otherwise the type must be a projected type, so just format the full name - interpolatedStringHandler.AppendLiteral(type.FullName); - } } - AppendRuntimeClassName(ref handler, type, useWindowsUIXamlProjections); - return handler.ToStringAndClear(); } } diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index f623ee4b4..36afe8df7 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -423,6 +423,11 @@ public InteropReferences( /// public TypeReference ReadOnlyCollection1 => field ??= _corLibTypeFactory.CorLibScope.CreateTypeReference("System.Collections.ObjectModel"u8, "ReadOnlyCollection`1"u8); + /// + /// Gets the for . + /// + public TypeReference NotifyCollectionChangedAction => field ??= SystemObjectModel.CreateTypeReference("System.Collections.Specialized"u8, "NotifyCollectionChangedAction"u8); + /// /// Gets the for . /// @@ -598,6 +603,11 @@ public InteropReferences( /// public TypeReference WindowsRuntimeClassNameAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeClassNameAttribute"u8); + /// + /// Gets the for WindowsRuntime.WindowsRuntimeMetadataTypeNameAttribute. + /// + public TypeReference WindowsRuntimeMetadataTypeNameAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeMetadataTypeNameAttribute"u8); + /// /// Gets the for . /// @@ -608,6 +618,16 @@ public InteropReferences( /// public TypeReference WindowsRuntimeMetadataAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeMetadataAttribute"u8); + /// + /// Gets the for WindowsRuntime.WindowsRuntimeMappedMetadataAttribute. + /// + public TypeReference WindowsRuntimeMappedMetadataAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeMappedMetadataAttribute"u8); + + /// + /// Gets the for WindowsRuntime.WindowsRuntimeReferenceTypeAttribute. + /// + public TypeReference WindowsRuntimeReferenceTypeAttribute => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime"u8, "WindowsRuntimeReferenceTypeAttribute"u8); + /// /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeManagedOnlyTypeAttribute. /// @@ -623,6 +643,11 @@ public InteropReferences( /// public TypeReference WindowsRuntimeComWrappersTypeMapGroup => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeComWrappersTypeMapGroup"u8); + /// + /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeMetadataTypeMapGroup. + /// + public TypeReference WindowsRuntimeMetadataTypeMapGroup => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "WindowsRuntimeMetadataTypeMapGroup"u8); + /// /// Gets the for WindowsRuntime.InteropServices.DynamicInterfaceCastableImplementationTypeMapGroup. /// @@ -1323,6 +1348,11 @@ public InteropReferences( /// public TypeReference TrustLevel => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "TrustLevel"u8); + /// + /// Gets the for Windows.Foundation.PropertyType. + /// + public TypeReference PropertyType => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "PropertyType"u8); + /// /// Gets the for Windows.Foundation.Point. /// @@ -1338,6 +1368,11 @@ public InteropReferences( /// public TypeReference Size => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "Size"u8); + /// + /// Gets the for Windows.Foundation.IStringable. + /// + public TypeReference IStringable => field ??= _windowsRuntimeModule.CreateTypeReference("Windows.Foundation"u8, "IStringable"u8); + /// /// Gets the for Windows.Foundation.AsyncStatus. /// @@ -1460,6 +1495,16 @@ public InteropReferences( /// public MemberReference TypeMapAssociationAttributeWindowsRuntimeComWrappersTypeMapGroup_ctor => field ??= TypeMapAssociationAttribute1_ctor(WindowsRuntimeComWrappersTypeMapGroup.ToReferenceTypeSignature()); + /// + /// Gets the for , using . + /// + public MemberReference TypeMapAttributeWindowsRuntimeMetadataTypeMapGroup_ctor_TrimTarget => field ??= TypeMapAttribute1_ctor_TrimTarget(WindowsRuntimeMetadataTypeMapGroup.ToReferenceTypeSignature()); + + /// + /// Gets the for , using . + /// + public MemberReference TypeMapAssociationAttributeWindowsRuntimeMetadataTypeMapGroup_ctor => field ??= TypeMapAssociationAttribute1_ctor(WindowsRuntimeMetadataTypeMapGroup.ToReferenceTypeSignature()); + /// /// Gets the for , using . /// @@ -1471,6 +1516,70 @@ public InteropReferences( public MemberReference IDisposableDispose => field ??= IDisposable .CreateMemberReference("Dispose"u8, MethodSignature.CreateInstance(_corLibTypeFactory.Void)); + /// + /// Gets the for 's adder. + /// + public MemberReference ICommandadd_CanExecuteChanged => field ??= ICommand + .CreateMemberReference("add_CanExecuteChanged"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [EventHandler.ToReferenceTypeSignature()])); + + /// + /// Gets the for 's remover. + /// + public MemberReference ICommandremove_CanExecuteChanged => field ??= ICommand + .CreateMemberReference("remove_CanExecuteChanged"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [EventHandler.ToReferenceTypeSignature()])); + + /// + /// Gets the for . + /// + public MemberReference ICommandCanExecute => field ??= ICommand + .CreateMemberReference("CanExecute"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Boolean, + parameterTypes: [_corLibTypeFactory.Object])); + + /// + /// Gets the for . + /// + public MemberReference ICommandExecute => field ??= ICommand + .CreateMemberReference("Execute"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [_corLibTypeFactory.Object])); + + /// + /// Gets the for 's adder. + /// + public MemberReference INotifyCollectionChangedadd_CollectionChanged => field ??= INotifyCollectionChanged + .CreateMemberReference("add_CollectionChanged"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [NotifyCollectionChangedEventHandler.ToReferenceTypeSignature()])); + + /// + /// Gets the for 's remover. + /// + public MemberReference INotifyCollectionChangedremove_CollectionChanged => field ??= INotifyCollectionChanged + .CreateMemberReference("remove_CollectionChanged"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [NotifyCollectionChangedEventHandler.ToReferenceTypeSignature()])); + + /// + /// Gets the for 's adder. + /// + public MemberReference INotifyPropertyChangedadd_PropertyChanged => field ??= INotifyPropertyChanged + .CreateMemberReference("add_PropertyChanged"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [PropertyChangedEventHandler.ToReferenceTypeSignature()])); + + /// + /// Gets the for 's remover. + /// + public MemberReference INotifyPropertyChangedremove_PropertyChanged => field ??= INotifyPropertyChanged + .CreateMemberReference("remove_PropertyChanged"u8, MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [PropertyChangedEventHandler.ToReferenceTypeSignature()])); + /// /// Gets the for . /// @@ -2256,6 +2365,22 @@ public InteropReferences( returnType: _corLibTypeFactory.Void, parameterTypes: [_corLibTypeFactory.String])); + /// + /// Gets the for 's constructor. + /// + public MemberReference WindowsRuntimeMetadataTypeNameAttribute_ctor => field ??= WindowsRuntimeMetadataTypeNameAttribute + .CreateMemberReference(".ctor", MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [_corLibTypeFactory.String])); + + /// + /// Gets the for 's constructor. + /// + public MemberReference WindowsRuntimeMappedMetadataAttribute_ctor => field ??= WindowsRuntimeMappedMetadataAttribute + .CreateMemberReference(".ctor", MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [_corLibTypeFactory.String])); + /// /// Gets the for 's constructor. /// @@ -2264,6 +2389,14 @@ public InteropReferences( returnType: _corLibTypeFactory.Void, parameterTypes: [Type.ToReferenceTypeSignature()])); + /// + /// Gets the for 's constructor. + /// + public MemberReference WindowsRuntimeReferenceTypeAttribute_ctor => field ??= WindowsRuntimeReferenceTypeAttribute + .CreateMemberReference(".ctor", MethodSignature.CreateInstance( + returnType: _corLibTypeFactory.Void, + parameterTypes: [Type.ToReferenceTypeSignature()])); + /// /// Gets the for WindowsRuntime.InteropServices.WindowsRuntimeObjectMarshaller.ConvertToManaged(void*). /// diff --git a/src/WinRT.Runtime2/ABI/System/Boolean.cs b/src/WinRT.Runtime2/ABI/System/Boolean.cs index 080ad37f4..6c668aa2c 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`1", target: typeof(ABI.System.Boolean), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 c314c66bf..4cbe37317 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`1", target: typeof(ABI.System.Byte), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 521a2bf35..9161ddd52 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`1", target: typeof(ABI.System.Char), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[WindowsRuntimeMetadataTypeName("Char16")] +[WindowsRuntimeMappedType(typeof(char))] +[WindowsRuntimeReferenceType(typeof(char?))] [CharComWrappersMarshaller] file static class Char; diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs index c5aad7627..7c1601d3d 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs @@ -21,21 +21,7 @@ namespace ABI.System.Collections; /// -/// ABI type for . -/// -/// -/// This interface is equivalent to . -/// -/// -[IEnumerableComWrappersMarshaller] -[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, - DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, - UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] -[EditorBrowsable(EditorBrowsableState.Never)] -public static class IEnumerable; - -/// -/// Marshaller for . +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -44,20 +30,20 @@ public static class IEnumerable; public static unsafe class IEnumerableMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.Collections.IEnumerable? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IEnumerable? value) { - return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IBindableIterable); + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IBindableIterable); } /// - public static global::System.Collections.IEnumerable? ConvertToManaged(void* value) + public static IEnumerable? ConvertToManaged(void* value) { - return (global::System.Collections.IEnumerable?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); + return (IEnumerable?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); } } /// -/// The implementation for . +/// The implementation for . /// file abstract class IEnumerableComWrappersCallback : IWindowsRuntimeUnsealedObjectComWrappersCallback { @@ -99,9 +85,13 @@ public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wr } /// -/// A custom implementation for . +/// A custom implementation for . /// -file sealed unsafe class IEnumerableComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class IEnumerableComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute { /// public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) @@ -116,7 +106,7 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper } /// -/// Interop methods for . +/// Interop methods for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -124,15 +114,15 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper [EditorBrowsable(EditorBrowsableState.Never)] public static class IEnumerableMethods { - /// - public static global::System.Collections.IEnumerator GetEnumerator(WindowsRuntimeObjectReference thisReference) + /// + public static IEnumerator GetEnumerator(WindowsRuntimeObjectReference thisReference) { return BindableIEnumerableMethods.GetEnumerator(thisReference); } } /// -/// The implementation. +/// The implementation. /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -141,7 +131,7 @@ public static class IEnumerableMethods public static unsafe class IEnumerableImpl { /// - /// The value for the managed implementation. + /// The value for the managed implementation. /// [FixedAddressValueType] private static readonly IBindableIterableVftbl Vftbl; @@ -157,7 +147,7 @@ static IEnumerableImpl() } /// - /// Gets a pointer to the managed implementation. + /// Gets a pointer to the managed implementation. /// public static nint Vtable { @@ -176,7 +166,7 @@ private static HRESULT First(void* thisPtr, void** result) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); BindableIEnumerableAdapter.First(thisObject, result); @@ -190,19 +180,19 @@ private static HRESULT First(void* thisPtr, void** result) } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] [Guid("036D2C08-DF29-41AF-8AA2-D774BE62BA6F")] -file interface IEnumerableInterfaceImpl : global::System.Collections.IEnumerable +file interface IEnumerableInterfaceImpl : IEnumerable { - global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() + IEnumerator IEnumerable.GetEnumerator() { WindowsRuntimeObject thisObject = (WindowsRuntimeObject)this; // First, try to lookup for the actual 'IEnumerable' interface being implemented if (thisObject.TryGetObjectReferenceForInterface( - interfaceType: typeof(global::System.Collections.IEnumerable).TypeHandle, + interfaceType: typeof(IEnumerable).TypeHandle, interfaceReference: out WindowsRuntimeObjectReference? interfaceReference)) { return IEnumerableMethods.GetEnumerator(interfaceReference); diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs index 372be5b13..b6138a335 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs @@ -21,21 +21,7 @@ namespace ABI.System.Collections; /// -/// ABI type for . -/// -/// -/// This interface is equivalent to . -/// -/// -[IEnumeratorComWrappersMarshaller] -[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, - DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, - UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] -[EditorBrowsable(EditorBrowsableState.Never)] -public static class IEnumerator; - -/// -/// Marshaller for . +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -44,20 +30,20 @@ public static class IEnumerator; public static unsafe class IEnumeratorMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.Collections.IEnumerator? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IEnumerator? value) { - return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IBindableIterator); + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IBindableIterator); } /// - public static global::System.Collections.IEnumerator? ConvertToManaged(void* value) + public static IEnumerator? ConvertToManaged(void* value) { - return (global::System.Collections.IEnumerator?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); + return (IEnumerator?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); } } /// -/// The implementation for . +/// The implementation for . /// file abstract class IEnumeratorComWrappersCallback : IWindowsRuntimeUnsealedObjectComWrappersCallback { @@ -99,9 +85,13 @@ public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wr } /// -/// A custom implementation for . +/// A custom implementation for . /// -file sealed unsafe class IEnumeratorComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class IEnumeratorComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute { /// public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) @@ -116,7 +106,7 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper } /// -/// Interop methods for . +/// Interop methods for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -124,13 +114,13 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper [EditorBrowsable(EditorBrowsableState.Never)] public static class IEnumeratorMethods { - /// + /// public static object? Current(WindowsRuntimeObjectReference thisReference) { return IBindableIteratorMethods.Current(thisReference); } - /// + /// [MethodImpl(MethodImplOptions.NoInlining)] public static bool MoveNext(WindowsRuntimeObjectReference thisReference) { @@ -139,7 +129,7 @@ public static bool MoveNext(WindowsRuntimeObjectReference thisReference) } /// -/// The implementation. +/// The implementation. /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -148,7 +138,7 @@ public static bool MoveNext(WindowsRuntimeObjectReference thisReference) public static unsafe class IEnumeratorImpl { /// - /// The value for the managed implementation. + /// The value for the managed implementation. /// [FixedAddressValueType] private static readonly IBindableIteratorVftbl Vftbl; @@ -167,7 +157,7 @@ static IEnumeratorImpl() } /// - /// Gets a pointer to the managed implementation. + /// Gets a pointer to the managed implementation. /// public static nint Vtable { @@ -186,7 +176,7 @@ private static HRESULT get_Current(void* thisPtr, void** result) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? current = BindableIEnumeratorAdapter.GetInstance(thisObject).Current; @@ -211,7 +201,7 @@ private static HRESULT get_HasCurrent(void* thisPtr, bool* result) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); *result = BindableIEnumeratorAdapter.GetInstance(thisObject).HasCurrent; @@ -234,7 +224,7 @@ private static HRESULT MoveNext(void* thisPtr, bool* result) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); *result = BindableIEnumeratorAdapter.GetInstance(thisObject).MoveNext(); @@ -255,33 +245,33 @@ private static HRESULT GetMany(void* thisPtr, uint index, void* items, uint* cou } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] [Guid("6A1D6C07-076D-49F2-8314-F52C9C9A8331")] -file interface IEnumeratorInterfaceImpl : global::System.Collections.IEnumerator +file interface IEnumeratorInterfaceImpl : IEnumerator { /// - object? global::System.Collections.IEnumerator.Current + object? IEnumerator.Current { get { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IEnumerator).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IEnumerator).TypeHandle); return IEnumeratorMethods.Current(thisReference); } } /// - bool global::System.Collections.IEnumerator.MoveNext() + bool IEnumerator.MoveNext() { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IEnumerator).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IEnumerator).TypeHandle); return IEnumeratorMethods.MoveNext(thisReference); } /// - void global::System.Collections.IEnumerator.Reset() + void IEnumerator.Reset() { throw new NotSupportedException(); } diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IList.cs b/src/WinRT.Runtime2/ABI/System/Collections/IList.cs index b53a17163..87fea7a82 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/IList.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/IList.cs @@ -25,21 +25,7 @@ namespace ABI.System.Collections; /// -/// ABI type for . -/// -/// -/// This interface is equivalent to . -/// -/// -[IListComWrappersMarshaller] -[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, - DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, - UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] -[EditorBrowsable(EditorBrowsableState.Never)] -public static class IList; - -/// -/// Marshaller for . +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -48,20 +34,20 @@ public static class IList; public static unsafe class IListMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.Collections.IList? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(IList? value) { - return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IBindableVector); + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IBindableVector); } /// - public static global::System.Collections.IList? ConvertToManaged(void* value) + public static IList? ConvertToManaged(void* value) { - return (global::System.Collections.IList?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); + return (IList?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); } } /// -/// The implementation for . +/// The implementation for . /// file abstract class IListComWrappersCallback : IWindowsRuntimeUnsealedObjectComWrappersCallback { @@ -103,9 +89,13 @@ public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wr } /// -/// A custom implementation for . +/// A custom implementation for . /// -file sealed unsafe class IListComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class IListComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute { /// public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) @@ -120,7 +110,7 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper } /// -/// Interop methods for . +/// Interop methods for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -140,55 +130,55 @@ public static void CopyTo(WindowsRuntimeObjectReference thisReference, Array arr BindableIListMethods.CopyTo(thisReference, array, index); } - /// + /// public static object? Item(WindowsRuntimeObjectReference thisReference, int index) { return BindableIListMethods.Item(thisReference, index); } - /// + /// public static void Item(WindowsRuntimeObjectReference thisReference, int index, object? value) { BindableIListMethods.Item(thisReference, index, value); } - /// + /// public static int Add(WindowsRuntimeObjectReference thisReference, object? value) { return BindableIListMethods.Add(thisReference, value); } - /// + /// public static bool Contains(WindowsRuntimeObjectReference thisReference, object? value) { return BindableIListMethods.Contains(thisReference, value); } - /// + /// public static int IndexOf(WindowsRuntimeObjectReference thisReference, object? value) { return BindableIListMethods.IndexOf(thisReference, value); } - /// + /// public static void Insert(WindowsRuntimeObjectReference thisReference, int index, object? value) { BindableIListMethods.Insert(thisReference, index, value); } - /// + /// public static void Remove(WindowsRuntimeObjectReference thisReference, object? value) { BindableIListMethods.Remove(thisReference, value); } - /// + /// public static void RemoveAt(WindowsRuntimeObjectReference thisReference, int index) { BindableIListMethods.RemoveAt(thisReference, index); } - /// + /// public static void Clear(WindowsRuntimeObjectReference thisReference) { BindableIListMethods.Clear(thisReference); @@ -196,7 +186,7 @@ public static void Clear(WindowsRuntimeObjectReference thisReference) } /// -/// The implementation. +/// The implementation. /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -205,7 +195,7 @@ public static void Clear(WindowsRuntimeObjectReference thisReference) public static unsafe class IListImpl { /// - /// The value for the managed implementation. + /// The value for the managed implementation. /// [FixedAddressValueType] private static readonly IBindableVectorVftbl Vftbl; @@ -230,7 +220,7 @@ static IListImpl() } /// - /// Gets a pointer to the managed implementation. + /// Gets a pointer to the managed implementation. /// public static nint Vtable { @@ -249,7 +239,7 @@ private static HRESULT GetAt(void* thisPtr, uint index, void** result) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? value = BindableIListAdapter.GetAt(thisObject, index); @@ -274,7 +264,7 @@ private static HRESULT get_Size(void* thisPtr, uint* size) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); *size = BindableIListAdapter.Size(thisObject); @@ -297,7 +287,7 @@ private static HRESULT GetView(void* thisPtr, void** view) try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); BindableIReadOnlyListAdapter adapter = BindableIListAdapter.GetView(thisObject); @@ -322,7 +312,7 @@ private static HRESULT IndexOf(void* thisPtr, void* value, uint* index, bool* re try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); @@ -342,7 +332,7 @@ private static HRESULT SetAt(void* thisPtr, uint index, void* value) { try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); @@ -362,7 +352,7 @@ private static HRESULT InsertAt(void* thisPtr, uint index, void* value) { try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); @@ -382,7 +372,7 @@ private static HRESULT RemoveAt(void* thisPtr, uint index) { try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); BindableIListAdapter.RemoveAt(thisObject, index); @@ -400,7 +390,7 @@ private static HRESULT Append(void* thisPtr, void* value) { try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); @@ -420,7 +410,7 @@ private static HRESULT RemoveAtEnd(void* thisPtr) { try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); BindableIListAdapter.RemoveAtEnd(thisObject); @@ -438,7 +428,7 @@ private static HRESULT Clear(void* thisPtr) { try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); BindableIListAdapter.Clear(thisObject); @@ -452,87 +442,87 @@ private static HRESULT Clear(void* thisPtr) } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] [Guid("393DE7DE-6FD0-4C0D-BB71-47244A113E93")] -file interface IListInterfaceImpl : global::System.Collections.IList +file interface IListInterfaceImpl : IList { /// - object? global::System.Collections.IList.this[int index] + object? IList.this[int index] { get { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); return BindableIListMethods.Item(thisReference, index); } set { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); BindableIListMethods.Item(thisReference, index, value); } } /// - bool global::System.Collections.IList.IsFixedSize => false; + bool IList.IsFixedSize => false; /// - bool global::System.Collections.IList.IsReadOnly => false; + bool IList.IsReadOnly => false; /// - int global::System.Collections.IList.Add(object? value) + int IList.Add(object? value) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); return BindableIListMethods.Add(thisReference, value); } /// - void global::System.Collections.IList.Clear() + void IList.Clear() { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); BindableIListMethods.Clear(thisReference); } /// - bool global::System.Collections.IList.Contains(object? value) + bool IList.Contains(object? value) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); return BindableIListMethods.Contains(thisReference, value); } /// - int global::System.Collections.IList.IndexOf(object? value) + int IList.IndexOf(object? value) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); return BindableIListMethods.IndexOf(thisReference, value); } /// - void global::System.Collections.IList.Insert(int index, object? value) + void IList.Insert(int index, object? value) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); BindableIListMethods.Insert(thisReference, index, value); } /// - void global::System.Collections.IList.Remove(object? value) + void IList.Remove(object? value) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); BindableIListMethods.Remove(thisReference, value); } /// - void global::System.Collections.IList.RemoveAt(int index) + void IList.RemoveAt(int index) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); BindableIListMethods.RemoveAt(thisReference, index); } @@ -542,7 +532,7 @@ int ICollection.Count { get { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); return BindableIListMethods.Count(thisReference); } @@ -557,7 +547,7 @@ int ICollection.Count /// void ICollection.CopyTo(Array array, int index) { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::System.Collections.IList).TypeHandle); + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(IList).TypeHandle); BindableIListMethods.CopyTo(thisReference, array, index); } diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IReadOnlyList.cs b/src/WinRT.Runtime2/ABI/System/Collections/IReadOnlyList.cs new file mode 100644 index 000000000..fce2dcfe0 --- /dev/null +++ b/src/WinRT.Runtime2/ABI/System/Collections/IReadOnlyList.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using WindowsRuntime; +using WindowsRuntime.InteropServices; + +namespace ABI.System.Collections; + +/// +/// A custom implementation for IReadOnlyList. +/// +/// +/// +/// There is no non-generic type in .NET, however this +/// type still uses "IReadOnlyList" in its name to match the naming convention of adapter types matching .NET type names. +/// +/// +/// Because this interface is not projected, only the marshaller attribute type and the proxy type are needed. The proxy +/// type will be generated at compile time, as its runtime class name will depend on the XAML configuration being used. +/// +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class IReadOnlyListComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +{ + /// + public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) + { + WindowsRuntimeObjectReference valueReference = WindowsRuntimeComWrappersMarshal.CreateObjectReference( + externalComObject: value, + iid: in WellKnownWindowsInterfaceIIDs.IID_IBindableVectorView, + wrapperFlags: out wrapperFlags); + + return new WindowsRuntimeReadOnlyList(valueReference); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs index e380f081c..cb4bd9c62 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs @@ -193,30 +193,4 @@ private static HRESULT remove_CollectionChanged(void* thisPtr, EventRegistration return e.HResult; } } -} - -/// -/// The implementation for . -/// -[DynamicInterfaceCastableImplementation] -file interface INotifyCollectionChangedInterfaceImpl : INotifyCollectionChanged -{ - /// - event NotifyCollectionChangedEventHandler? INotifyCollectionChanged.CollectionChanged - { - add - { - var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(INotifyCollectionChanged).TypeHandle); - - INotifyCollectionChangedMethods.CollectionChanged((WindowsRuntimeObject)this, thisReference).Subscribe(value); - } - remove - { - var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(INotifyCollectionChanged).TypeHandle); - - INotifyCollectionChangedMethods.CollectionChanged(thisObject, thisReference).Unsubscribe(value); - } - } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedAction.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedAction.cs new file mode 100644 index 000000000..21ee72f22 --- /dev/null +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedAction.cs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using WindowsRuntime; +using WindowsRuntime.InteropServices; +using WindowsRuntime.InteropServices.Marshalling; +using static System.Runtime.InteropServices.ComWrappers; + +#pragma warning disable IDE1006, CA1416 + +namespace ABI.System.Collections.Specialized; + +/// +/// Marshaller for . +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class NotifyCollectionChangedActionMarshaller +{ + /// + public static WindowsRuntimeObjectReferenceValue BoxToUnmanaged(NotifyCollectionChangedAction? value) + { + return WindowsRuntimeValueTypeMarshaller.BoxToUnmanaged(value, CreateComInterfaceFlags.None, in WellKnownXamlInterfaceIIDs.IID_IReferenceOfNotifyCollectionChangedAction); + } + + /// + public static NotifyCollectionChangedAction? UnboxToManaged(void* value) + { + return WindowsRuntimeValueTypeMarshaller.UnboxToManaged(value); + } +} + +/// +/// The set of values for . +/// +file struct NotifyCollectionChangedActionInterfaceEntries +{ + public ComInterfaceEntry IReferenceOfNotifyCollectionChangedAction; + public ComInterfaceEntry IPropertyValue; + public ComInterfaceEntry IStringable; + public ComInterfaceEntry IWeakReferenceSource; + public ComInterfaceEntry IMarshal; + public ComInterfaceEntry IAgileObject; + public ComInterfaceEntry IInspectable; + public ComInterfaceEntry IUnknown; +} + +/// +/// The implementation of . +/// +file static class NotifyCollectionChangedActionInterfaceEntriesImpl +{ + /// + /// The value for . + /// + [FixedAddressValueType] + public static readonly NotifyCollectionChangedActionInterfaceEntries Entries; + + /// + /// Initializes . + /// + static NotifyCollectionChangedActionInterfaceEntriesImpl() + { + Entries.IReferenceOfNotifyCollectionChangedAction.IID = WellKnownXamlInterfaceIIDs.IID_IReferenceOfNotifyCollectionChangedAction; + Entries.IReferenceOfNotifyCollectionChangedAction.Vtable = IReferenceImpl.Int32Enum; + Entries.IPropertyValue.IID = WellKnownWindowsInterfaceIIDs.IID_IPropertyValue; + Entries.IPropertyValue.Vtable = IPropertyValueImpl.OtherTypeVtable; + Entries.IStringable.IID = WellKnownWindowsInterfaceIIDs.IID_IStringable; + Entries.IStringable.Vtable = IStringableImpl.Vtable; + Entries.IWeakReferenceSource.IID = WellKnownWindowsInterfaceIIDs.IID_IWeakReferenceSource; + Entries.IWeakReferenceSource.Vtable = IWeakReferenceSourceImpl.Vtable; + Entries.IMarshal.IID = WellKnownWindowsInterfaceIIDs.IID_IMarshal; + Entries.IMarshal.Vtable = IMarshalImpl.Vtable; + Entries.IAgileObject.IID = WellKnownWindowsInterfaceIIDs.IID_IAgileObject; + Entries.IAgileObject.Vtable = IAgileObjectImpl.Vtable; + Entries.IInspectable.IID = WellKnownWindowsInterfaceIIDs.IID_IInspectable; + Entries.IInspectable.Vtable = IInspectableImpl.Vtable; + Entries.IUnknown.IID = WellKnownWindowsInterfaceIIDs.IID_IUnknown; + Entries.IUnknown.Vtable = IUnknownImpl.Vtable; + } +} + +/// +/// A custom implementation for . +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class NotifyCollectionChangedActionComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +{ + /// + public override void* GetOrCreateComInterfaceForObject(object value) + { + return WindowsRuntimeComWrappersMarshal.GetOrCreateComInterfaceForObject(value, CreateComInterfaceFlags.None); + } + + /// + public override ComInterfaceEntry* ComputeVtables(out int count) + { + count = sizeof(NotifyCollectionChangedActionInterfaceEntries) / sizeof(ComInterfaceEntry); + + return (ComInterfaceEntry*)Unsafe.AsPointer(in NotifyCollectionChangedActionInterfaceEntriesImpl.Entries); + } + + /// + public override object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) + { + wrapperFlags = CreatedWrapperFlags.NonWrapping; + + return WindowsRuntimeValueTypeMarshaller.UnboxToManagedUnsafe(value, in WellKnownXamlInterfaceIIDs.IID_IReferenceOfNotifyCollectionChangedAction); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs index e955235cf..721a04a2d 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventArgs.cs @@ -12,26 +12,10 @@ #pragma warning disable IDE0008, IDE0055 -[assembly: TypeMapAssociation( - typeof(NotifyCollectionChangedEventArgs), - typeof(ABI.System.Collections.Specialized.NotifyCollectionChangedEventArgs))] - namespace ABI.System.Collections.Specialized; /// -/// ABI type for . -/// -/// -/// -[NotifyCollectionChangedEventArgsComWrappersMarshaller] -[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, - DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, - UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] -[EditorBrowsable(EditorBrowsableState.Never)] -public static class NotifyCollectionChangedEventArgs; - -/// -/// Marshaller for . +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -40,7 +24,7 @@ public static class NotifyCollectionChangedEventArgs; public static unsafe class NotifyCollectionChangedEventArgsMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.Collections.Specialized.NotifyCollectionChangedEventArgs? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(NotifyCollectionChangedEventArgs? value) { if (value is null) { @@ -59,7 +43,7 @@ public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::Syst /// [MethodImpl(MethodImplOptions.NoInlining)] - public static global::System.Collections.Specialized.NotifyCollectionChangedEventArgs? ConvertToManaged(void* value) + public static NotifyCollectionChangedEventArgs? ConvertToManaged(void* value) { if (value is null) { @@ -165,14 +149,18 @@ static int GetOldStartingIndex(void* value) } /// -/// A custom implementation for . +/// A custom implementation for . /// -file sealed unsafe class NotifyCollectionChangedEventArgsComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class NotifyCollectionChangedEventArgsComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute { /// public override void* GetOrCreateComInterfaceForObject(object value) { - var args = (global::System.Collections.Specialized.NotifyCollectionChangedEventArgs)value; + var args = (NotifyCollectionChangedEventArgs)value; return NotifyCollectionChangedEventArgsRuntimeClassFactory.CreateInstance( args.Action, @@ -190,7 +178,7 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper IUnknownVftbl.QueryInterfaceUnsafe( thisPtr: value, - iid: in WellKnownXamlInterfaceIIDs.IID_INotifyCollectionChangedEventArgs, + iid: in WellKnownXamlInterfaceIIDs.IID_NotifyCollectionChangedEventArgs, pvObject: out void* result).Assert(); try @@ -205,7 +193,7 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper } /// -/// The runtime class factory for . +/// The runtime class factory for . /// file static unsafe class NotifyCollectionChangedEventArgsRuntimeClassFactory { @@ -217,14 +205,14 @@ file static unsafe class NotifyCollectionChangedEventArgsRuntimeClassFactory iid: in WellKnownXamlInterfaceIIDs.IID_INotifyCollectionChangedEventArgsFactory); /// - /// Creates a new native instance for . + /// Creates a new native instance for . /// - /// - /// - /// - /// - /// - /// The new native instance for . + /// + /// + /// + /// + /// + /// The new native instance for . [MethodImpl(MethodImplOptions.NoInlining)] public static void* CreateInstance( NotifyCollectionChangedAction action, diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs index 40e21cfbc..9dcfdef51 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs @@ -56,7 +56,7 @@ public static WindowsRuntimeObjectReferenceValue BoxToUnmanaged(NotifyCollection file static unsafe class NotifyCollectionChangedEventHandlerNativeDelegate { /// - public static void Invoke(this WindowsRuntimeObjectReference objectReference, object? sender, global::System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + public static void Invoke(this WindowsRuntimeObjectReference objectReference, object? sender, NotifyCollectionChangedEventArgs e) { using WindowsRuntimeObjectReferenceValue thisValue = objectReference.AsValue(); using WindowsRuntimeObjectReferenceValue senderValue = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(sender); diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandlerEventSource.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandlerEventSource.cs index 5dcbd3c27..f763851ff 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandlerEventSource.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandlerEventSource.cs @@ -27,7 +27,7 @@ public NotifyCollectionChangedEventHandlerEventSource(WindowsRuntimeObjectRefere /// protected override WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(NotifyCollectionChangedEventHandler value) { - return ABI.System.Collections.Specialized.NotifyCollectionChangedEventHandlerMarshaller.ConvertToUnmanaged(value); + return NotifyCollectionChangedEventHandlerMarshaller.ConvertToUnmanaged(value); } /// diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/DataErrorsChangedEventArgs.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/DataErrorsChangedEventArgs.cs index 28d3bb6fc..2d6ab1139 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/DataErrorsChangedEventArgs.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/DataErrorsChangedEventArgs.cs @@ -26,6 +26,9 @@ namespace ABI.System.ComponentModel; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Microsoft.UI.Xaml.WinUIContract")] +[WindowsRuntimeClassName("Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs")] +[WindowsRuntimeMappedType(typeof(global::System.ComponentModel.DataErrorsChangedEventArgs))] [DataErrorsChangedEventArgsComWrappersMarshaller] file static class DataErrorsChangedEventArgs; diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs index 4772b9931..f1a3842e7 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 thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); *result = thisObject.HasErrors; @@ -233,7 +256,7 @@ private static HRESULT add_ErrorsChanged(void* thisPtr, void* handler, EventRegi try { - var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = 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 thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); if (thisObject is not null && ErrorsChanged.TryGetValue(thisObject, 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 thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); IEnumerable managedResult = thisObject.GetErrors(HStringMarshaller.ConvertToManaged(propertyName)); @@ -304,46 +327,46 @@ static extern WindowsRuntimeObjectReferenceValue ConvertToUnmanaged( } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] [Guid("0EE6C2CC-273E-567D-BC0A-1DD87EE51EBA")] -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/ComponentModel/INotifyPropertyChanged.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs index ccdf11cd4..1b80d2552 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs @@ -194,30 +194,4 @@ private static HRESULT remove_PropertyChanged(void* thisPtr, EventRegistrationTo return e.HResult; } } -} - -/// -/// The implementation for . -/// -[DynamicInterfaceCastableImplementation] -file interface INotifyPropertyChangedInterfaceImpl : INotifyPropertyChanged -{ - /// - event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged - { - add - { - var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(INotifyPropertyChanged).TypeHandle); - - INotifyPropertyChangedMethods.PropertyChanged((WindowsRuntimeObject)this, thisReference).Subscribe(value); - } - remove - { - var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(INotifyPropertyChanged).TypeHandle); - - INotifyPropertyChangedMethods.PropertyChanged(thisObject, thisReference).Unsubscribe(value); - } - } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventArgs.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventArgs.cs index f2726af89..72e458041 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventArgs.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventArgs.cs @@ -9,26 +9,10 @@ using WindowsRuntime.InteropServices; using WindowsRuntime.InteropServices.Marshalling; -[assembly: TypeMapAssociation( - typeof(PropertyChangedEventArgs), - typeof(ABI.System.ComponentModel.PropertyChangedEventArgs))] - namespace ABI.System.ComponentModel; /// -/// ABI type for . -/// -/// -/// -[PropertyChangedEventArgsComWrappersMarshaller] -[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, - DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, - UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] -[EditorBrowsable(EditorBrowsableState.Never)] -public static class PropertyChangedEventArgs; - -/// -/// Marshaller for . +/// Marshaller for . /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -37,14 +21,14 @@ public static class PropertyChangedEventArgs; public static unsafe class PropertyChangedEventArgsMarshaller { /// - public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::System.ComponentModel.PropertyChangedEventArgs? value) + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(PropertyChangedEventArgs? value) { return value is null ? default : new(PropertyChangedEventArgsRuntimeClassFactory.CreateInstance(value.PropertyName)); } /// [MethodImpl(MethodImplOptions.NoInlining)] - public static global::System.ComponentModel.PropertyChangedEventArgs? ConvertToManaged(void* value) + public static PropertyChangedEventArgs? ConvertToManaged(void* value) { if (value is null) { @@ -59,7 +43,7 @@ public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::Syst // Convert to a managed 'string' and create the managed object for the args as well try { - return new global::System.ComponentModel.PropertyChangedEventArgs(HStringMarshaller.ConvertToManaged(propertyName)); + return new PropertyChangedEventArgs(HStringMarshaller.ConvertToManaged(propertyName)); } finally { @@ -69,14 +53,18 @@ public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::Syst } /// -/// A custom implementation for . +/// A custom implementation for . /// -file sealed unsafe class PropertyChangedEventArgsComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public sealed unsafe class PropertyChangedEventArgsComWrappersMarshallerAttribute : WindowsRuntimeComWrappersMarshallerAttribute { /// public override void* GetOrCreateComInterfaceForObject(object value) { - return PropertyChangedEventArgsRuntimeClassFactory.CreateInstance(((global::System.ComponentModel.PropertyChangedEventArgs)value).PropertyName); + return PropertyChangedEventArgsRuntimeClassFactory.CreateInstance(((PropertyChangedEventArgs)value).PropertyName); } /// @@ -102,7 +90,7 @@ public override object CreateObject(void* value, out CreatedWrapperFlags wrapper } /// -/// The runtime class factory for . +/// The runtime class factory for . /// file static unsafe class PropertyChangedEventArgsRuntimeClassFactory { @@ -114,10 +102,10 @@ file static unsafe class PropertyChangedEventArgsRuntimeClassFactory iid: in WellKnownXamlInterfaceIIDs.IID_PropertyChangedEventArgsRuntimeClassFactory); /// - /// Creates a new native instance for . + /// Creates a new native instance for . /// /// The property name to use. - /// The new native instance for . + /// The new native instance for . [MethodImpl(MethodImplOptions.NoInlining)] public static void* CreateInstance(string? propertyName) { diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs index d7dc50c23..d457f3e19 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs @@ -55,7 +55,7 @@ public static WindowsRuntimeObjectReferenceValue BoxToUnmanaged(PropertyChangedE file static unsafe class PropertyChangedEventHandlerNativeDelegate { /// - public static void Invoke(this WindowsRuntimeObjectReference objectReference, object? sender, global::System.ComponentModel.PropertyChangedEventArgs e) + public static void Invoke(this WindowsRuntimeObjectReference objectReference, object? sender, PropertyChangedEventArgs e) { using WindowsRuntimeObjectReferenceValue thisValue = objectReference.AsValue(); using WindowsRuntimeObjectReferenceValue senderValue = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(sender); diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandlerEventSource.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandlerEventSource.cs index b0bdd0db3..23ce3bda8 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandlerEventSource.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandlerEventSource.cs @@ -26,7 +26,7 @@ public PropertyChangedEventHandlerEventSource(WindowsRuntimeObjectReference nati /// protected override WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(PropertyChangedEventHandler value) { - return ABI.System.ComponentModel.PropertyChangedEventHandlerMarshaller.ConvertToUnmanaged(value); + return PropertyChangedEventHandlerMarshaller.ConvertToUnmanaged(value); } /// diff --git a/src/WinRT.Runtime2/ABI/System/DateTimeOffset.cs b/src/WinRT.Runtime2/ABI/System/DateTimeOffset.cs index cdb80ba2d..e0e9ff87b 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`1", target: typeof(ABI.System.DateTimeOffset), @@ -28,7 +33,11 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 324296fff..3cb89fb29 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`1", target: typeof(ABI.System.Double), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 b4d4d930b..84568d376 100644 --- a/src/WinRT.Runtime2/ABI/System/EventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/EventHandler.cs @@ -31,6 +31,7 @@ namespace ABI.System; // All native objects reporting their runtime class name as 'Windows.Foundation.IReference`1>' // will be marshalled as 'EventHandler'. We only special case marshalling to managed from an exact pointer to a native // delegate instance. This is mostly just needed to allow implementing 'ICommand.CanExecuteChanged' over native objects. +// - We also don't use '[WindowsRuntimeMappedMetadata]', so when marshalling 'typeof(EventHandler)', it will be a custom type. // // This is also why some ABI methods for 'EventHandler' are either missing or not implemented. diff --git a/src/WinRT.Runtime2/ABI/System/Exception.cs b/src/WinRT.Runtime2/ABI/System/Exception.cs index 35c491ae9..f7910c85e 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`1", target: typeof(ABI.System.Exception), @@ -28,7 +33,10 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 ee3d42801..726a87355 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`1", target: typeof(ABI.System.Guid), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 9976aea90..fc1b2fdb4 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,16 +148,16 @@ private static HRESULT Close(void* thisPtr) } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] [Guid("30D5A829-7FA4-4026-83BB-D75BAE4EA99E")] -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 467afcb5f..d963e7d0a 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 thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); global::System.Type? managedType = TypeMarshaller.ConvertToManaged(serviceType); @@ -157,16 +180,16 @@ private static HRESULT GetService(void* thisPtr, Type serviceType, void** result } /// -/// The implementation for . +/// The implementation for . /// [DynamicInterfaceCastableImplementation] [Guid("68B3A2DF-8173-539F-B524-C8A2348F5AFB")] -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 04a9eceec..737f8f0b2 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`1", target: typeof(ABI.System.Int16), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 059387d4e..8027851cb 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`1", target: typeof(ABI.System.Int32), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 90b5e5066..16e56d333 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`1", target: typeof(ABI.System.Int64), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 961c84282..749ddbf80 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`1", 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`1")] +[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 6ae0ad045..9f94ecaf3 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`1", 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`1")] +[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 fdc3561b7..fe5ff5323 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`1", 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`1")] +[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 3d433e97e..dced508ef 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`1", 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`1")] +[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 d38c10f1e..dabd87f76 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`1", 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`1")] +[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 b98d37e25..e463900f3 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`1", 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`1")] +[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 93037f809..8368e3f2a 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`1", 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`1")] +[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 6785bbb21..a051b2ee1 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`1", target: typeof(ABI.System.Single), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 24b7b8f18..0ae612ae6 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`1", target: typeof(ABI.System.String), @@ -28,7 +33,10 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 67672353b..27fb0b68c 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`1", target: typeof(ABI.System.TimeSpan), @@ -28,7 +33,11 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 c2637c68d..6ea224173 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`1", target: typeof(ABI.System.Type), @@ -34,7 +40,10 @@ namespace ABI.System; /// ABI type for . /// /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.UniversalApiContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[WindowsRuntimeMetadataTypeName("Windows.UI.Xaml.Interop.TypeName")] +[WindowsRuntimeMappedType(typeof(global::System.Type))] [TypeComWrappersMarshaller] [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, @@ -92,10 +101,164 @@ 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); + + // Special handling for some types which can never be used in a 'Nullable' instantiation (e.g. interfaces) + if (nullableUnderlyingType is null) + { + // 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 (!value.IsGenericType && value.IsDefined(typeof(WindowsRuntimeMetadataAttribute))) + { + reference = new TypeReference { Name = value.FullName, Kind = TypeKind.Metadata }; + + return; + } + + // 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 (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'. + // This will also handle generic delegate types, which will also use '[WindowsRuntimeMetadataTypeName]'. + if (marshallingInfo.TryGetMetadataTypeName(out string? metadataTypeName)) + { + reference = new TypeReference { Name = metadataTypeName, Kind = kind }; + + return; + } + + // If the type is 'KeyValuePair<,>', we are guaranteed to have a runtime class name on the proxy type. + // Note that because this type is a reference type in the Windows Runtime type system, the runtime class + // name will be the correct name to use here, as it will just be the 'IKeyValuePair<,>' interface type. + // This is why we don't need additional attributes for the metadata type name in this specific scenario. + if (typeOrUnderlyingType.IsValueType && + typeOrUnderlyingType.IsGenericType && + typeOrUnderlyingType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + reference = new TypeReference { Name = marshallingInfo.GetRuntimeClassName(), 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 of these is true: + // - The value type is not generic (the only possible case would've been 'KeyValuePair<,>') + // - The delegate is not generic (or the proxy type would've had a metadata name on it) + // 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; + } + } + + // 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 +285,89 @@ 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); + } + + // 'IBindableVectorView' has no equivalent .NET type, so we just return 'null' here. This needs + // to be special-cased, or it would end up resolving a marshalling info instance (because the + // external type map still has an entry for this name, for marshalling), and then fail because + // there's no associated public type for the resulting proxy type retrieved from the type map. + if (typeName.SequenceEqual(WellKnownXamlRuntimeClassNames.IBindableVectorView)) + { + return null; + } + } + + global::System.Type? type = null; + + // 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); + } + + if (publicType.IsValueType) + { + // 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.IsGenericType && + publicType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + type = publicType; + } + else + { + // For other 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 = marshallingInfo.ReferenceType; + } + } + else + { + // Otherwise, just use the public type directly + type = 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 83ae103e9..236f032b3 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`1", target: typeof(ABI.System.UInt16), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 00ffe4090..1789d62bf 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`1", target: typeof(ABI.System.UInt32), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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 a2565417d..66bff493e 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`1", target: typeof(ABI.System.UInt64), @@ -27,7 +32,11 @@ namespace ABI.System; /// /// ABI type for . /// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[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/System/Windows.Input/ICommand.cs b/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs index cddaf89fa..faf4ce394 100644 --- a/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs +++ b/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs @@ -270,47 +270,4 @@ private static HRESULT Execute(void* thisPtr, void* parameter) return RestrictedErrorInfoExceptionMarshaller.ConvertToUnmanaged(e); } } -} - -/// -/// The implementation for . -/// -[DynamicInterfaceCastableImplementation] -[Guid("E5AF3542-CA67-4081-995B-709DD13792DF")] -file interface ICommandInterfaceImpl : ICommand -{ - /// - event EventHandler? ICommand.CanExecuteChanged - { - add - { - var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(ICommand).TypeHandle); - - ICommandMethods.CanExecuteChanged((WindowsRuntimeObject)this, thisReference).Subscribe(value); - } - remove - { - var thisObject = (WindowsRuntimeObject)this; - var thisReference = thisObject.GetObjectReferenceForInterface(typeof(ICommand).TypeHandle); - - ICommandMethods.CanExecuteChanged(thisObject, thisReference).Unsubscribe(value); - } - } - - /// - bool ICommand.CanExecute(object? parameter) - { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(ICommand).TypeHandle); - - return ICommandMethods.CanExecute(thisReference, parameter); - } - - /// - void ICommand.Execute(object? parameter) - { - var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(ICommand).TypeHandle); - - ICommandMethods.Execute(thisReference, parameter); - } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs index 544859c4c..1b28d99b7 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`1", target: typeof(AsyncActionCompletedHandler), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncStatus.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncStatus.cs index 60e046c63..a48763a1b 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncStatus.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncStatus.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.AsyncStatus", + target: typeof(AsyncStatus), + trimTarget: typeof(AsyncStatus))] + [assembly: TypeMap( value: "Windows.Foundation.IReference`1", target: typeof(AsyncStatus), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/CollectionChange.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/CollectionChange.cs index bf5ab1107..7528ac029 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`1", 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 d848be3c6..2743c2f97 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 3f5329eb5..1293279ac 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(IAsyncAction), + 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 93842e80d..b4d0ab989 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/IStringable.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/IStringable.cs new file mode 100644 index 000000000..22ac08de7 --- /dev/null +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/IStringable.cs @@ -0,0 +1,280 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Windows.Foundation; +using WindowsRuntime; +using WindowsRuntime.InteropServices; +using WindowsRuntime.InteropServices.Marshalling; +using static System.Runtime.InteropServices.ComWrappers; + +#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.IStringable", + target: typeof(ABI.Windows.Foundation.IStringable), + trimTarget: typeof(IStringable))] +#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code + +[assembly: TypeMapAssociation( + source: typeof(IStringable), + proxy: typeof(ABI.Windows.Foundation.IStringable))] + +[assembly: TypeMapAssociation( + source: typeof(IStringable), + proxy: typeof(ABI.Windows.Foundation.IStringableInterfaceImpl))] + +namespace ABI.Windows.Foundation; + +/// +/// ABI type for . +/// +[WindowsRuntimeMappedMetadata("Windows.Foundation.FoundationContract")] +[WindowsRuntimeMetadataTypeName("Windows.Foundation.IStringable")] +[WindowsRuntimeMappedType(typeof(global::Windows.Foundation.IStringable))] +file static class IStringable; + +/// +/// Marshaller for . +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class IStringableMarshaller +{ + /// + public static WindowsRuntimeObjectReferenceValue ConvertToUnmanaged(global::Windows.Foundation.IStringable? value) + { + return WindowsRuntimeInterfaceMarshaller.ConvertToUnmanaged(value, in WellKnownWindowsInterfaceIIDs.IID_IStringable); + } + + /// + public static global::Windows.Foundation.IStringable? ConvertToManaged(void* value) + { + return (global::Windows.Foundation.IStringable?)WindowsRuntimeUnsealedObjectMarshaller.ConvertToManaged(value); + } +} + +/// +/// The implementation for . +/// +file abstract class IStringableComWrappersCallback : IWindowsRuntimeUnsealedObjectComWrappersCallback +{ + /// + public static unsafe bool TryCreateObject( + void* value, + ReadOnlySpan runtimeClassName, + [NotNullWhen(true)] out object? wrapperObject, + out CreatedWrapperFlags wrapperFlags) + { + // Here we match the runtime class name of 'IStringable', as usual for marshalling interfaces (which handles them being + // returned from anonymous objects implementing them), as well as 'Uri'. The reason for this special handling is that + // 'System.Uri' is a custom-mapped type, and it doesn't implement 'Windows.Foundation.IStringable'. However, the native + // 'Windows.Foundation.Uri' type does implement it. This specific issue only happens with this interface and this type. + // Without this special handling, we'd get 'Windows.Foundation.Uri' as the runtime class name, which would then cause + // our marshalling infrastructure to return a 'System.Uri' instance, resulting in the following interface cast to fail. + if (runtimeClassName.SequenceEqual("Windows.Foundation.IStringable") || + runtimeClassName.SequenceEqual("Windows.Foundation.Uri")) + { + WindowsRuntimeObjectReference valueReference = WindowsRuntimeComWrappersMarshal.CreateObjectReferenceUnsafe( + externalComObject: value, + iid: in WellKnownWindowsInterfaceIIDs.IID_IStringable, + wrapperFlags: out wrapperFlags); + + wrapperObject = new WindowsRuntimeStringable(valueReference); + + return true; + } + + wrapperFlags = CreatedWrapperFlags.None; + wrapperObject = null; + + return false; + } + + /// + public static unsafe object CreateObject(void* value, out CreatedWrapperFlags wrapperFlags) + { + WindowsRuntimeObjectReference valueReference = WindowsRuntimeComWrappersMarshal.CreateObjectReferenceUnsafe( + externalComObject: value, + iid: in WellKnownWindowsInterfaceIIDs.IID_IStringable, + wrapperFlags: out wrapperFlags); + + return new WindowsRuntimeStringable(valueReference); + } +} + +/// +/// The implementation of a projected anonymous object. +/// +[WindowsRuntimeManagedOnlyType] +file sealed class WindowsRuntimeStringable : WindowsRuntimeObject, + global::Windows.Foundation.IStringable, + IWindowsRuntimeInterface +{ + /// + /// Creates a instance with the specified parameters. + /// + /// The inner Windows Runtime object reference to wrap in the current instance. + /// Thrown if is . + public WindowsRuntimeStringable(WindowsRuntimeObjectReference nativeObjectReference) + : base(nativeObjectReference) + { + } + + /// + [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] + protected internal override bool HasUnwrappableNativeObjectReference => true; + + /// + public override string ToString() + { + return IStringableMethods.ToString(NativeObjectReference); + } + + /// + WindowsRuntimeObjectReferenceValue IWindowsRuntimeInterface.GetInterface() + { + return NativeObjectReference.AsValue(); + } + + /// + [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] + protected override bool IsOverridableInterface(in Guid iid) + { + return false; + } +} + +/// +/// Interop methods for . +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class IStringableMethods +{ + /// + [MethodImpl(MethodImplOptions.NoInlining)] + public static string ToString(WindowsRuntimeObjectReference thisReference) + { + using WindowsRuntimeObjectReferenceValue thisValue = thisReference.AsValue(); + + void* thisPtr = thisValue.GetThisPtrUnsafe(); + + HSTRING result; + + RestrictedErrorInfo.ThrowExceptionForHR(((IStringableVftbl*)*(void***)thisPtr)->ToString(thisPtr, &result)); + + try + { + return HStringMarshaller.ConvertToManaged(result); + } + finally + { + HStringMarshaller.Free(result); + } + } +} + +/// +/// Binding type for . +/// +[StructLayout(LayoutKind.Sequential)] +internal unsafe struct IStringableVftbl +{ + public delegate* unmanaged[MemberFunction] QueryInterface; + public delegate* unmanaged[MemberFunction] AddRef; + public delegate* unmanaged[MemberFunction] Release; + public delegate* unmanaged[MemberFunction] GetIids; + public delegate* unmanaged[MemberFunction] GetRuntimeClassName; + public delegate* unmanaged[MemberFunction] GetTrustLevel; + public new delegate* unmanaged[MemberFunction] ToString; +} + +/// +/// The implementation. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static unsafe class IStringableImpl +{ + /// + /// The value for the managed implementation. + /// + [FixedAddressValueType] + private static readonly IStringableVftbl Vftbl; + + /// + /// Initializes . + /// + static IStringableImpl() + { + *(IInspectableVftbl*)Unsafe.AsPointer(ref Vftbl) = *(IInspectableVftbl*)IInspectableImpl.Vtable; + + Vftbl.ToString = &ToString; + } + + /// + /// Gets a pointer to the managed implementation. + /// + public static nint Vtable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => (nint)Unsafe.AsPointer(in Vftbl); + } + + /// + [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] + private static HRESULT ToString(void* thisPtr, HSTRING* result) + { + if (result is null) + { + return WellKnownErrorCodes.E_POINTER; + } + + try + { + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + + *result = HStringMarshaller.ConvertToUnmanaged(thisObject.ToString()); + + return WellKnownErrorCodes.S_OK; + } + catch (Exception e) + { + return RestrictedErrorInfoExceptionMarshaller.ConvertToUnmanaged(e); + } + } +} + +/// +/// The implementation for . +/// +[DynamicInterfaceCastableImplementation] +[Guid("96369F54-8EB6-48F0-ABCE-C1B211E627C3")] +file interface IStringableInterfaceImpl : global::Windows.Foundation.IStringable +{ + /// + string global::Windows.Foundation.IStringable.ToString() + { + var thisReference = ((WindowsRuntimeObject)this).GetObjectReferenceForInterface(typeof(global::Windows.Foundation.IStringable).TypeHandle); + + return IStringableMethods.ToString(thisReference); + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Point.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Point.cs index 0fe3f087f..f6877757a 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`1", target: typeof(Point), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/PropertyType.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/PropertyType.cs index 00fc4608a..8982afa5a 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/PropertyType.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/PropertyType.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.PropertyType", + target: typeof(PropertyType), + trimTarget: typeof(PropertyType))] + [assembly: TypeMap( value: "Windows.Foundation.IReference`1", target: typeof(PropertyType), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Rect.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Rect.cs index 316d54c11..49de7b265 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`1", target: typeof(Rect), diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Size.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Size.cs index c8a3c8e72..3e502df0a 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`1", 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/Bindables/WindowsRuntimeEnumerable.cs b/src/WinRT.Runtime2/Bindables/WindowsRuntimeEnumerable.cs index c7f81f8e8..3cfb05256 100644 --- a/src/WinRT.Runtime2/Bindables/WindowsRuntimeEnumerable.cs +++ b/src/WinRT.Runtime2/Bindables/WindowsRuntimeEnumerable.cs @@ -30,7 +30,7 @@ public WindowsRuntimeEnumerable(WindowsRuntimeObjectReference nativeObjectRefere DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] - protected internal sealed override bool HasUnwrappableNativeObjectReference => true; + protected internal override bool HasUnwrappableNativeObjectReference => true; /// public IEnumerator GetEnumerator() @@ -49,7 +49,7 @@ WindowsRuntimeObjectReferenceValue IWindowsRuntimeInterface.GetInte DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] - protected sealed override bool IsOverridableInterface(in Guid iid) + protected override bool IsOverridableInterface(in Guid iid) { return false; } diff --git a/src/WinRT.Runtime2/Bindables/WindowsRuntimeList.cs b/src/WinRT.Runtime2/Bindables/WindowsRuntimeList.cs index 47b275fd7..22c165c22 100644 --- a/src/WinRT.Runtime2/Bindables/WindowsRuntimeList.cs +++ b/src/WinRT.Runtime2/Bindables/WindowsRuntimeList.cs @@ -57,7 +57,7 @@ WindowsRuntimeObjectReference InitializeIIterableObjectReference() DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] - protected internal sealed override bool HasUnwrappableNativeObjectReference => true; + protected internal override bool HasUnwrappableNativeObjectReference => true; /// public bool IsFixedSize => false; @@ -152,7 +152,7 @@ WindowsRuntimeObjectReferenceValue IWindowsRuntimeInterface.GetInte DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] - protected sealed override bool IsOverridableInterface(in Guid iid) + protected override bool IsOverridableInterface(in Guid iid) { return false; } diff --git a/src/WinRT.Runtime2/Bindables/WindowsRuntimeReadOnlyList.cs b/src/WinRT.Runtime2/Bindables/WindowsRuntimeReadOnlyList.cs new file mode 100644 index 000000000..9fe64254e --- /dev/null +++ b/src/WinRT.Runtime2/Bindables/WindowsRuntimeReadOnlyList.cs @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Threading; +using WindowsRuntime.InteropServices; + +namespace WindowsRuntime; + +/// +/// The implementation of all projected Windows Runtime readonly types. +/// +/// +/// +/// There is no IReadOnlyList interface in .NET, so this type only implements . +/// This still provides better performance when casting to that interface for enumeration than having to go through +/// an opaque marshalled object and using . +/// +[WindowsRuntimeManagedOnlyType] +internal sealed class WindowsRuntimeReadOnlyList : WindowsRuntimeObject, + IEnumerable, + IWindowsRuntimeInterface +{ + /// + /// Creates a instance with the specified parameters. + /// + /// The inner Windows Runtime object reference to wrap in the current instance. + /// Thrown if is . + public WindowsRuntimeReadOnlyList(WindowsRuntimeObjectReference nativeObjectReference) + : base(nativeObjectReference) + { + } + + /// + /// Gets the lazy-loaded, cached object reference for Windows.UI.Xaml.Interop.IBindableIterable for the current object. + /// + private WindowsRuntimeObjectReference IBindableIterableObjectReference + { + get + { + [MethodImpl(MethodImplOptions.NoInlining)] + WindowsRuntimeObjectReference InitializeIIterableObjectReference() + { + _ = Interlocked.CompareExchange( + location1: ref field, + value: NativeObjectReference.As(in WellKnownWindowsInterfaceIIDs.IID_IBindableIterable), + comparand: null); + + return field; + } + + return field ?? InitializeIIterableObjectReference(); + } + } + + /// + [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] + protected internal override bool HasUnwrappableNativeObjectReference => true; + + /// + public IEnumerator GetEnumerator() + { + return ABI.System.Collections.IEnumerableMethods.GetEnumerator(IBindableIterableObjectReference); + } + + /// + WindowsRuntimeObjectReferenceValue IWindowsRuntimeInterface.GetInterface() + { + return IBindableIterableObjectReference.AsValue(); + } + + /// + [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] + [EditorBrowsable(EditorBrowsableState.Never)] + protected override bool IsOverridableInterface(in Guid iid) + { + return false; + } +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Collections/IObservableMapMethodsImpl{TKey, TValue}.cs b/src/WinRT.Runtime2/InteropServices/Collections/IObservableMapMethodsImpl{TKey, TValue}.cs index 3cd18b7df..a5cb80770 100644 --- a/src/WinRT.Runtime2/InteropServices/Collections/IObservableMapMethodsImpl{TKey, TValue}.cs +++ b/src/WinRT.Runtime2/InteropServices/Collections/IObservableMapMethodsImpl{TKey, TValue}.cs @@ -24,5 +24,5 @@ public interface IObservableMapMethodsImpl /// The instance to use to invoke the native method. /// The instance associated with . /// - static abstract global::ABI.Windows.Foundation.Collections.MapChangedEventHandlerEventSource MapChanged(WindowsRuntimeObject thisObject, WindowsRuntimeObjectReference thisReference); + static abstract ABI.Windows.Foundation.Collections.MapChangedEventHandlerEventSource MapChanged(WindowsRuntimeObject thisObject, WindowsRuntimeObjectReference thisReference); } \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Collections/IObservableVectorMethodsImpl{T}.cs b/src/WinRT.Runtime2/InteropServices/Collections/IObservableVectorMethodsImpl{T}.cs index a7abaf81c..8610321ee 100644 --- a/src/WinRT.Runtime2/InteropServices/Collections/IObservableVectorMethodsImpl{T}.cs +++ b/src/WinRT.Runtime2/InteropServices/Collections/IObservableVectorMethodsImpl{T}.cs @@ -23,5 +23,5 @@ public interface IObservableVectorMethodsImpl /// The instance to use to invoke the native method. /// The instance associated with . /// - static abstract global::ABI.Windows.Foundation.Collections.VectorChangedEventHandlerEventSource VectorChanged(WindowsRuntimeObject thisObject, WindowsRuntimeObjectReference thisReference); + static abstract ABI.Windows.Foundation.Collections.VectorChangedEventHandlerEventSource VectorChanged(WindowsRuntimeObject thisObject, WindowsRuntimeObjectReference thisReference); } \ 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 744eee580..8b590c358 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`1")] +[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/ObjectReference/WindowsRuntimeObjectReferenceValue.cs b/src/WinRT.Runtime2/InteropServices/ObjectReference/WindowsRuntimeObjectReferenceValue.cs index ffdd4c38c..99a2a8370 100644 --- a/src/WinRT.Runtime2/InteropServices/ObjectReference/WindowsRuntimeObjectReferenceValue.cs +++ b/src/WinRT.Runtime2/InteropServices/ObjectReference/WindowsRuntimeObjectReferenceValue.cs @@ -136,7 +136,7 @@ public bool IsNull /// /// /// - /// This method is analogous to , but with one crucial + /// This method is analogous to , but with one crucial /// difference. That is: calling this method more than once is undefined behavior. /// /// diff --git a/src/WinRT.Runtime2/InteropServices/Placeholders/DynamicInterfaceCastableForwarderAttributePlaceholder.cs b/src/WinRT.Runtime2/InteropServices/Placeholders/DynamicInterfaceCastableForwarderAttributePlaceholder.cs new file mode 100644 index 000000000..e912ea17b --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Placeholders/DynamicInterfaceCastableForwarderAttributePlaceholder.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Diagnostics.CodeAnalysis; + +namespace WindowsRuntime.InteropServices; + +/// +/// A placeholder type. +/// +internal sealed class DynamicInterfaceCastableForwarderAttributePlaceholder : DynamicInterfaceCastableForwarderAttribute +{ + /// + /// The shared placeholder instance. + /// + public static DynamicInterfaceCastableForwarderAttributePlaceholder Instance = new(); + + /// + public override bool IsInterfaceImplemented(WindowsRuntimeObject thisReference, [NotNullWhen(true)] out WindowsRuntimeObjectReference? interfaceReference) + { + interfaceReference = null; + + return false; + } +} \ No newline at end of file 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/ProjectionImpls/IInspectableImpl.cs b/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IInspectableImpl.cs index 933b7e793..27d6f3f97 100644 --- a/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IInspectableImpl.cs +++ b/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IInspectableImpl.cs @@ -56,9 +56,18 @@ private static HRESULT GetIids(void* thisPtr, uint* iidCount, Guid** iids) { object instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + // Get the marshalling info for the current object. Note that we don't necessary have an exact match. + // For instance, consider the scenario where 'typeof(Foo)' has been marshalled as 'object' to native. + // The CCW would be for a concrete 'RuntimeType' instance, which we can't know about. This logic + // takes care of finding the best marshalling info match for similar cases (e.g. for 'Exception' too). + if (!WindowsRuntimeMarshallingInfo.TryGetInfo(instance.GetType(), out WindowsRuntimeMarshallingInfo? marshallingInfo)) + { + marshallingInfo = WindowsRuntimeMarshallingInfo.GetOpaqueInfo(instance); + } + // Get the managed CCW vtable entries to gather the IIDs. This method should only be used with // managed objects that were produced by 'WindowsRuntimeComWrappers', so this should never fail. - WindowsRuntimeVtableInfo vtableInfo = WindowsRuntimeMarshallingInfo.GetInfo(instance.GetType()).GetVtableInfo(); + WindowsRuntimeVtableInfo vtableInfo = marshallingInfo.GetVtableInfo(); Guid* pIids = (Guid*)Marshal.AllocCoTaskMem(sizeof(Guid) * vtableInfo.Count); @@ -87,8 +96,14 @@ private static HRESULT GetRuntimeClassName(void* thisPtr, HSTRING* className) { object instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + // Get the marshalling info for the current object (see additional notes above) + if (!WindowsRuntimeMarshallingInfo.TryGetInfo(instance.GetType(), out WindowsRuntimeMarshallingInfo? marshallingInfo)) + { + marshallingInfo = WindowsRuntimeMarshallingInfo.GetOpaqueInfo(instance); + } + // Like for 'GetIids', this method should only be called on managed types, and it should never fail - string runtimeClassName = WindowsRuntimeMarshallingInfo.GetInfo(instance.GetType()).GetRuntimeClassName(); + string runtimeClassName = marshallingInfo.GetRuntimeClassName(); *className = HStringMarshaller.ConvertToUnmanaged(runtimeClassName); 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 faba2af02..0e7001101 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 DynamicInterfaceCastableForwarderAttribute? fo { DynamicInterfaceCastableForwarderAttribute? value = ImplementationType.GetCustomAttribute(inherit: false); - value ??= PlaceholderDynamicInterfaceCastableForwarderAttribute.Instance; + value ??= DynamicInterfaceCastableForwarderAttributePlaceholder.Instance; _implementationForwarder = value; - if (value is not (null or PlaceholderDynamicInterfaceCastableForwarderAttribute)) + if (value is not (null or DynamicInterfaceCastableForwarderAttributePlaceholder)) { forwarder = value; @@ -148,7 +148,7 @@ bool Load([NotNullWhen(true)] out DynamicInterfaceCastableForwarderAttribute? fo // We have a cached forwarder, so return it immediately if (value is not null) { - if (value is PlaceholderDynamicInterfaceCastableForwarderAttribute) + if (value is DynamicInterfaceCastableForwarderAttributePlaceholder) { forwarder = null; @@ -180,22 +180,3 @@ bool Load([NotNullWhen(true)] out DynamicInterfaceCastableForwarderAttribute? fo return null; } } - -/// -/// A placeholder type. -/// -file sealed class PlaceholderDynamicInterfaceCastableForwarderAttribute : DynamicInterfaceCastableForwarderAttribute -{ - /// - /// The shared placeholder instance. - /// - public static PlaceholderDynamicInterfaceCastableForwarderAttribute Instance = new(); - - /// - public override bool IsInterfaceImplemented(WindowsRuntimeObject thisReference, [NotNullWhen(true)] out WindowsRuntimeObjectReference? interfaceReference) - { - interfaceReference = 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..5bedf6606 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; } /// @@ -139,10 +175,23 @@ Type InitializePublicType() // public type yet. We can do that here. WindowsRuntimeMappedTypeAttribute mappedTypeAttribute = _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 public type. " + + $"This code path should have never been reached. Please file an issue at https://github.com/microsoft/CsWinRT."); + } + // In this scenario, it is guaranteed that the '[WindowsRuntimeMappedType]' attribute will be present on the // metadata provider type, as we would not have any way to go back to the associated public type otherwise, // which is needed in some cases. The attribute being missing would indicate some code generation error. - Debug.Assert(mappedTypeAttribute is not null); + if (mappedTypeAttribute is null) + { + ThrowNotSupportedException(); + } // Cache the public type for later. We don't need a compare exchange here, as even if we did concurrent // queries for this value, the result would always be the same. So we can skip that small overhead here. @@ -153,6 +202,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. /// @@ -325,6 +449,36 @@ public static bool TryGetInfo(Type managedType, [NotNullWhen(true)] out WindowsR return result is not null; } + /// + /// Gets the value to marshal an opaque (managed) object. + /// + /// The managed object to expose outside the .NET runtime. + /// The value to use to marshal . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static WindowsRuntimeMarshallingInfo GetOpaqueInfo(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 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 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 GetInfo(typeof(object)); + } + /// /// Gets the instance associated with the current metadata provider type. /// @@ -370,11 +524,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 +545,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 +597,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 +632,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; - ThrowNotSupportedException(); + return false; } - return _runtimeClassName ??= runtimeClassNameAttribute.RuntimeClassName; + _runtimeClassName = runtimeClassNameAttribute.RuntimeClassName; + + runtimeClassName = runtimeClassNameAttribute.RuntimeClassName; + + return true; } - return _runtimeClassName ?? InitializeRuntimeClassName(); + 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 ??= ""; + + metadataTypeName = null; + + return false; + } + + _metadataTypeName = metadataTypeNameAttribute.MetadataTypeName; + + metadataTypeName = metadataTypeNameAttribute.MetadataTypeName; + + return true; + } + + 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 +750,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 +777,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..b8f13152f --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/TypeMapInfo/WindowsRuntimeMetadataInfo.cs @@ -0,0 +1,227 @@ +// 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)!; + + [DoesNotReturn] + [StackTraceHidden] + void ThrowNotSupportedException() + { + throw new NotSupportedException( + $"The metadata provider type '{_metadataProviderType}' does not have an associated public type. " + + $"This code path should have never been reached. Please file an issue at https://github.com/microsoft/CsWinRT."); + } + + if (mappedTypeAttribute is null) + { + ThrowNotSupportedException(); + } + + 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/WellKnownInterfaceIIDs.g.cs b/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.g.cs index d6c6cdc4d..2a52094ec 100644 --- a/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.g.cs +++ b/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.g.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; @@ -58,7 +58,7 @@ public static ref readonly Guid IID_IInspectable get => ref WellKnownWindowsInterfaceIIDs.IID_IInspectable; } - /// The IID for IStringable. + /// The IID for IStringable (mapped to . public static ref readonly Guid IID_IStringable { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.tt b/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.tt index 32da8d6fe..805aa7672 100644 --- a/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.tt +++ b/src/WinRT.Runtime2/InteropServices/WellKnownInterfaceIIDs.tt @@ -1,4 +1,4 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ output extension=".g.cs"#> @@ -29,7 +29,7 @@ var entries = new (string ProjectedFullyQualifiedName, string WindowsRuntimeFull (null, "IMarshal", false), (null, "IMemoryBufferByteAccess", false), (null, "IInspectable", false), - (null, "IStringable", false), + ("Windows.Foundation.IStringable", "IStringable", false), (null, "IPropertyValue", false), (null, "IWeakReferenceSource", false), ("System.Collections.IEnumerable", "Windows.UI.Xaml.Interop.IBindableIterable", false), diff --git a/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.g.cs b/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.g.cs index 81b1c2a85..30a8be4b8 100644 --- a/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.g.cs +++ b/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.g.cs @@ -735,8 +735,8 @@ public static ref readonly Guid IID_WUX_INotifyCollectionChangedEventArgsFactory } } - /// The IID for MUX_INotifyCollectionChangedEventArgs (DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F). - public static ref readonly Guid IID_MUX_INotifyCollectionChangedEventArgs + /// The IID for MUX_NotifyCollectionChangedEventArgs (DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F). + public static ref readonly Guid IID_MUX_NotifyCollectionChangedEventArgs { [MethodImpl(MethodImplOptions.AggressiveInlining)] get @@ -760,8 +760,8 @@ public static ref readonly Guid IID_MUX_INotifyCollectionChangedEventArgs } } - /// The IID for WUX_INotifyCollectionChangedEventArgs (4CF68D33-E3F2-4964-B85E-945B4F7E2F21). - public static ref readonly Guid IID_WUX_INotifyCollectionChangedEventArgs + /// The IID for WUX_NotifyCollectionChangedEventArgs (4CF68D33-E3F2-4964-B85E-945B4F7E2F21). + public static ref readonly Guid IID_WUX_NotifyCollectionChangedEventArgs { [MethodImpl(MethodImplOptions.AggressiveInlining)] get @@ -3034,4 +3034,54 @@ public static ref readonly Guid IID_WUX_IReferenceOfNotifyCollectionChangedEvent return ref Unsafe.As(ref MemoryMarshal.GetReference(data)); } } + + /// The IID for MUX_IReferenceOfNotifyCollectionChangedAction (5F754C9D-BC42-56EA-96C0-70113DBD62A4). + public static ref readonly Guid IID_MUX_IReferenceOfNotifyCollectionChangedAction + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + ReadOnlySpan data = + [ + 0x9D, 0x4C, 0x75, 0x5F, + 0x42, 0xBC, + 0xEA, 0x56, + 0x96, + 0xC0, + 0x70, + 0x11, + 0x3D, + 0xBD, + 0x62, + 0xA4 + ]; + + return ref Unsafe.As(ref MemoryMarshal.GetReference(data)); + } + } + + /// The IID for WUX_IReferenceOfNotifyCollectionChangedAction (0FFB101A-BC7D-50C3-8193-55CDF7448FA2). + public static ref readonly Guid IID_WUX_IReferenceOfNotifyCollectionChangedAction + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + ReadOnlySpan data = + [ + 0x1A, 0x10, 0xFB, 0x0F, + 0x7D, 0xBC, + 0xC3, 0x50, + 0x81, + 0x93, + 0x55, + 0xCD, + 0xF7, + 0x44, + 0x8F, + 0xA2 + ]; + + return ref Unsafe.As(ref MemoryMarshal.GetReference(data)); + } + } } \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.tt b/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.tt index 83d411108..3cd1bce81 100644 --- a/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.tt +++ b/src/WinRT.Runtime2/InteropServices/WellKnownWindowsInterfaceIIDs.tt @@ -46,8 +46,8 @@ var entries = new (string Name, string IID)[] ("WUX_INotifyCollectionChanged", "28B167D5-1A31-465B-9B25-D5C3AE686C40"), ("MUX_INotifyCollectionChangedEventArgsFactory", "5108EBA4-4892-5A20-8374-A96815E0FD27"), ("WUX_INotifyCollectionChangedEventArgsFactory", "B30C3E3A-DF8D-44A5-9A38-7AC0D08CE63D"), - ("MUX_INotifyCollectionChangedEventArgs", "DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F"), - ("WUX_INotifyCollectionChangedEventArgs", "4CF68D33-E3F2-4964-B85E-945B4F7E2F21"), + ("MUX_NotifyCollectionChangedEventArgs", "DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F"), + ("WUX_NotifyCollectionChangedEventArgs", "4CF68D33-E3F2-4964-B85E-945B4F7E2F21"), ("MUX_NotifyCollectionChangedEventHandler", "8B0909DC-2005-5D93-BF8A-725F017BAA8D"), ("WUX_NotifyCollectionChangedEventHandler", "CA10B37C-F382-4591-8557-5E24965279B0"), ("MUX_PropertyChangedEventArgs", "63D0C952-396B-54F4-AF8C-BA8724A427BF"), @@ -137,7 +137,9 @@ var entries = new (string Name, string IID)[] ("MUX_IReferenceOfPropertyChangedEventHandler", "1EEAE0CB-8F57-5C37-A087-A55d46E2FE3F"), ("WUX_IReferenceOfPropertyChangedEventHandler", "B1A920A9-C2F2-5453-A53E-66B1294A8BFE"), ("MUX_IReferenceOfNotifyCollectionChangedEventHandler", "779D5A21-0E7d-5476-BB90-27FA3B4B8DE5"), - ("WUX_IReferenceOfNotifyCollectionChangedEventHandler", "A4FD5C6E-6549-59A9-86EF-5A490A1875D9") + ("WUX_IReferenceOfNotifyCollectionChangedEventHandler", "A4FD5C6E-6549-59A9-86EF-5A490A1875D9"), + ("MUX_IReferenceOfNotifyCollectionChangedAction", "5F754C9D-BC42-56EA-96C0-70113DBD62A4"), + ("WUX_IReferenceOfNotifyCollectionChangedAction", "0FFB101A-BC7D-50C3-8193-55CDF7448FA2") }; for (int i = 0; i < entries.Length; i++) diff --git a/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.g.cs b/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.g.cs index f2cfbfa5a..d27a0a8d2 100644 --- a/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.g.cs +++ b/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.g.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. using System; @@ -32,25 +32,25 @@ public static ref readonly Guid IID_INotifyCollectionChanged } /// - /// Gets the IID for INotifyCollectionChangedEventArgs. + /// Gets the IID for INotifyCollectionChangedEventArgsFactory. /// - public static ref readonly Guid IID_INotifyCollectionChangedEventArgs + public static ref readonly Guid IID_INotifyCollectionChangedEventArgsFactory { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => ref WindowsRuntimeFeatureSwitches.UseWindowsUIXamlProjections - ? ref WellKnownWindowsInterfaceIIDs.IID_WUX_INotifyCollectionChangedEventArgs - : ref WellKnownWindowsInterfaceIIDs.IID_MUX_INotifyCollectionChangedEventArgs; + ? ref WellKnownWindowsInterfaceIIDs.IID_WUX_INotifyCollectionChangedEventArgsFactory + : ref WellKnownWindowsInterfaceIIDs.IID_MUX_INotifyCollectionChangedEventArgsFactory; } /// - /// Gets the IID for INotifyCollectionChangedEventArgsFactory. + /// Gets the IID for NotifyCollectionChangedEventArgs. /// - public static ref readonly Guid IID_INotifyCollectionChangedEventArgsFactory + public static ref readonly Guid IID_NotifyCollectionChangedEventArgs { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => ref WindowsRuntimeFeatureSwitches.UseWindowsUIXamlProjections - ? ref WellKnownWindowsInterfaceIIDs.IID_WUX_INotifyCollectionChangedEventArgsFactory - : ref WellKnownWindowsInterfaceIIDs.IID_MUX_INotifyCollectionChangedEventArgsFactory; + ? ref WellKnownWindowsInterfaceIIDs.IID_WUX_NotifyCollectionChangedEventArgs + : ref WellKnownWindowsInterfaceIIDs.IID_MUX_NotifyCollectionChangedEventArgs; } /// @@ -108,6 +108,17 @@ public static ref readonly Guid IID_IReferenceOfPropertyChangedEventHandler : ref WellKnownWindowsInterfaceIIDs.IID_MUX_IReferenceOfPropertyChangedEventHandler; } + /// + /// Gets the IID for IReferenceOfNotifyCollectionChangedAction. + /// + public static ref readonly Guid IID_IReferenceOfNotifyCollectionChangedAction + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => ref WindowsRuntimeFeatureSwitches.UseWindowsUIXamlProjections + ? ref WellKnownWindowsInterfaceIIDs.IID_WUX_IReferenceOfNotifyCollectionChangedAction + : ref WellKnownWindowsInterfaceIIDs.IID_MUX_IReferenceOfNotifyCollectionChangedAction; + } + /// /// Gets the IID for IReferenceOfNotifyCollectionChangedEventHandler. /// diff --git a/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.tt b/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.tt index 37280a726..f07547a08 100644 --- a/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.tt +++ b/src/WinRT.Runtime2/InteropServices/WellKnownXamlInterfaceIIDs.tt @@ -1,4 +1,4 @@ -<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ template debug="false" hostspecific="false" language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Linq" #> <#@ output extension=".g.cs"#> @@ -18,14 +18,15 @@ var entries = new string[] { "INotifyPropertyChanged", "INotifyCollectionChanged", - "INotifyCollectionChangedEventArgs", "INotifyCollectionChangedEventArgsFactory", + "NotifyCollectionChangedEventArgs", "NotifyCollectionChangedEventHandler", "PropertyChangedEventArgs", "PropertyChangedEventArgsRuntimeClassFactory", "PropertyChangedEventHandler", "IReferenceOfPropertyChangedEventHandler", - "IReferenceOfNotifyCollectionChangedEventHandler" + "IReferenceOfNotifyCollectionChangedAction", + "IReferenceOfNotifyCollectionChangedEventHandler", }; for (int i = 0; i < entries.Length; i++) diff --git a/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs b/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs index c094baf50..5219917f7 100644 --- a/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs +++ b/src/WinRT.Runtime2/InteropServices/WindowsRuntimeComWrappers.cs @@ -189,11 +189,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 = WindowsRuntimeMarshallingInfo.GetOpaqueInfo(instance); thisPtr = (void*)GetOrCreateComInterfaceForObject(instance, CreateComInterfaceFlags.TrackerSupport); } @@ -297,11 +295,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 = WindowsRuntimeMarshallingInfo.GetOpaqueInfo(obj); } // Get the vtable from the current marshalling info (it will get cached in that instance) diff --git a/src/WinRT.Runtime2/Windows.Foundation/AsyncStatus.cs b/src/WinRT.Runtime2/Windows.Foundation/AsyncStatus.cs index a73e35c7a..e06e49c0a 100644 --- a/src/WinRT.Runtime2/Windows.Foundation/AsyncStatus.cs +++ b/src/WinRT.Runtime2/Windows.Foundation/AsyncStatus.cs @@ -13,6 +13,7 @@ namespace Windows.Foundation; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[WindowsRuntimeReferenceType(typeof(AsyncStatus?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.AsyncStatusComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.Foundation/Collections/CollectionChange.cs b/src/WinRT.Runtime2/Windows.Foundation/Collections/CollectionChange.cs index a0607a86c..3f5b381c9 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`1")] +[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/IStringable.cs b/src/WinRT.Runtime2/Windows.Foundation/IStringable.cs new file mode 100644 index 000000000..e599d1083 --- /dev/null +++ b/src/WinRT.Runtime2/Windows.Foundation/IStringable.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Runtime.InteropServices; +using Windows.Foundation.Metadata; +using WindowsRuntime; + +namespace Windows.Foundation; + +/// +/// Provides a way to represent the current object as a . +/// +/// +/// Managed types should not implement the interface. Rather, they should override the +/// method. When exposed to native code, they will implicitly get an implementation +/// of that will call the managed override. +/// +[WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] +[Guid("96369F54-8EB6-48F0-ABCE-C1B211E627C3")] +[ContractVersion(typeof(FoundationContract), 65536u)] +public interface IStringable +{ + /// + /// Gets a that represents the current object. + /// + /// The representation of the current object. + string ToString(); +} \ No newline at end of file diff --git a/src/WinRT.Runtime2/Windows.Foundation/Point.cs b/src/WinRT.Runtime2/Windows.Foundation/Point.cs index 4789b2fe7..23c0945b7 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`1")] +[WindowsRuntimeReferenceType(typeof(Point?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.PointComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.Foundation/PropertyType.cs b/src/WinRT.Runtime2/Windows.Foundation/PropertyType.cs index 99689ce2d..617fa6327 100644 --- a/src/WinRT.Runtime2/Windows.Foundation/PropertyType.cs +++ b/src/WinRT.Runtime2/Windows.Foundation/PropertyType.cs @@ -13,6 +13,7 @@ namespace Windows.Foundation; /// [WindowsRuntimeMetadata("Windows.Foundation.FoundationContract")] [WindowsRuntimeClassName("Windows.Foundation.IReference`1")] +[WindowsRuntimeReferenceType(typeof(PropertyType?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.PropertyTypeComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.Foundation/Rect.cs b/src/WinRT.Runtime2/Windows.Foundation/Rect.cs index 395ffbdd1..1f2d345de 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`1")] +[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 e70216d41..e2afc8cdb 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`1")] +[WindowsRuntimeReferenceType(typeof(Size?))] [SupportedOSPlatform("Windows10.0.10240.0")] [ContractVersion(typeof(FoundationContract), 65536u)] [ABI.Windows.Foundation.SizeComWrappersMarshaller] diff --git a/src/WinRT.Runtime2/Windows.UI.Xaml.Interop/TypeKind.cs b/src/WinRT.Runtime2/Windows.UI.Xaml.Interop/TypeKind.cs index 7167559de..963f9a2e0 100644 --- a/src/WinRT.Runtime2/Windows.UI.Xaml.Interop/TypeKind.cs +++ b/src/WinRT.Runtime2/Windows.UI.Xaml.Interop/TypeKind.cs @@ -11,7 +11,7 @@ namespace Windows.UI.Xaml.Interop; /// Provides basic guidance about the origin of a type. /// /// -/// This type is required for ABI projection of the class, but marshalling it is not supported. +/// This type is required for ABI projection of the class, but marshalling it is not supported. /// /// [Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, diff --git a/src/WinRT.Runtime2/WindowsRuntimeObject.cs b/src/WinRT.Runtime2/WindowsRuntimeObject.cs index 2e9e6f528..d5e115baa 100644 --- a/src/WinRT.Runtime2/WindowsRuntimeObject.cs +++ b/src/WinRT.Runtime2/WindowsRuntimeObject.cs @@ -871,7 +871,7 @@ private sealed class DynamicInterfaceCastableResult } /// - /// A dummy type to use for caching adaptive object references in . + /// A dummy type to use for caching adaptive object references in . /// private static class IEnumerableInstance; } \ No newline at end of file diff --git a/src/cswinrt.slnx b/src/cswinrt.slnx index 6e0af3fbc..f656521e7 100644 --- a/src/cswinrt.slnx +++ b/src/cswinrt.slnx @@ -324,6 +324,14 @@ + + + + + + + + diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index 48050f68f..8824557eb 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -1024,6 +1024,12 @@ namespace cswinrt if (auto mapping = get_mapped_type(type.TypeNamespace(), type.TypeName())) { + if (mapping->mapped_name == "IStringable") + { + w.write("global::WindowsRuntime.InteropServices.WellKnownInterfaceIIDs.IID_IStringable"); + return; + } + std::string name = w.write_temp("%", bind(type, typedef_name_type::NonProjected, true)); name = escape_type_name_for_identifier(name, true, true); w.write("global::WindowsRuntime.InteropServices.WellKnownInterfaceIIDs.IID_%", name); @@ -3166,6 +3172,16 @@ IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => global::AB objref_name); } + void write_nongeneric_enumerator_members_using_static_abi_methods(writer& w, std::string const& objref_name) + { + w.write(R"( +public bool MoveNext() => global::ABI.System.Collections.IEnumeratorMethods.MoveNext(%); +public void Reset() => throw new NotSupportedException(); +public object Current => global::ABI.System.Collections.IEnumeratorMethods.Current(%); +)", +objref_name, objref_name); + } + void write_nongeneric_enumerable_members(writer& w, std::string_view target) { w.write(R"( @@ -3898,6 +3914,10 @@ visibility, self, objref_name); { write_nongeneric_enumerable_members_using_static_abi_methods(w, objref_name); } + else if (mapping.mapped_namespace == "System.Collections" && mapping.mapped_name == "IEnumerator") + { + write_nongeneric_enumerator_members_using_static_abi_methods(w, objref_name); + } else if (mapping.mapped_namespace == "System.Collections" && mapping.mapped_name == "IList") { write_nongeneric_list_members_using_static_abi_methods(w, is_private, objref_name); @@ -4714,17 +4734,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) @@ -4764,13 +4814,18 @@ 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()); w.write("[WindowsRuntimeMetadata(\"%\")]\n", db_path.stem().string()); } - void write_struct_winrt_classname_attribute(writer& w, TypeDef const& type) + void write_value_type_winrt_classname_attribute(writer& w, TypeDef const& type) { if (settings.reference_projection) { @@ -9305,13 +9360,15 @@ internal unsafe struct %Vftbl w.write( R"( -%%%%% enum % : % +%%%%%%% enum % : % { )", is_flags_enum(type) ? "[FlagsAttribute]\n" : "", bind(type), + bind(type), bind(type, true), bind(type), + bind(type), (settings.internal) ? "internal" : "public", bind(type, typedef_name_type::Projected, false), enum_underlying_type); { @@ -9370,10 +9427,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), + bind(type), has_addition_to_type(type) ? " partial" : "", type.TypeName(), type.TypeName()); @@ -9434,7 +9492,7 @@ R"( if (!is_type_blittable(type)) { w.write("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n%%% unsafe struct %\n{\n", - bind(type), + bind(type), bind(type), internal_accessibility(), bind(type, typedef_name_type::ABI, false)); diff --git a/src/cswinrt/cswinrt.vcxproj b/src/cswinrt/cswinrt.vcxproj index 3eddc6443..0149e0f8e 100644 --- a/src/cswinrt/cswinrt.vcxproj +++ b/src/cswinrt/cswinrt.vcxproj @@ -1,7 +1,7 @@  + - 15.0 {6acfd2b2-e8aa-4cd4-aad8-213ce8bb2637} @@ -132,8 +132,8 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. - + \ No newline at end of file diff --git a/src/cswinrt/helpers.h b/src/cswinrt/helpers.h index eecf4d280..6e171e50c 100644 --- a/src/cswinrt/helpers.h +++ b/src/cswinrt/helpers.h @@ -781,6 +781,7 @@ namespace cswinrt { "Microsoft.UI.Xaml.Interop", { { "IBindableIterable", "System.Collections", "IEnumerable", true, true }, + { "IBindableIterator", "System.Collections", "IEnumerator", true, true }, { "IBindableVector", "System.Collections", "IList", true, true }, { "INotifyCollectionChanged", "System.Collections.Specialized", "INotifyCollectionChanged", true }, { "NotifyCollectionChangedAction", "System.Collections.Specialized", "NotifyCollectionChangedAction" }, @@ -844,6 +845,7 @@ namespace cswinrt { "IPropertyValue", "Windows.Foundation", "IPropertyValue", true }, { "IReferenceArray`1", "Windows.Foundation", "IReferenceArray", true }, { "IReference`1", "System", "Nullable`1", true }, + { "IStringable", "Windows.Foundation", "IStringable" }, { "Point", "Windows.Foundation", "Point" }, { "PropertyType", "Windows.Foundation", "PropertyType" }, { "Rect", "Windows.Foundation", "Rect" }, @@ -933,6 +935,7 @@ namespace cswinrt { "Windows.UI.Xaml.Interop", { { "IBindableIterable", "System.Collections", "IEnumerable", true, true }, + { "IBindableIterator", "System.Collections", "IEnumerator", true, true }, { "IBindableVector", "System.Collections", "IList", true, true }, { "INotifyCollectionChanged", "System.Collections.Specialized", "INotifyCollectionChanged", true }, { "NotifyCollectionChangedAction", "System.Collections.Specialized", "NotifyCollectionChangedAction" }, diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp index e1d0a8916..0dd5e133f 100644 --- a/src/cswinrt/main.cpp +++ b/src/cswinrt/main.cpp @@ -275,26 +275,39 @@ Where is one or more of: { case category::class_type: // For both static and attributes, we don't need to pass them across the ABI. - if (!is_static(type) && - !is_attribute_type(type)) + 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; } diff --git a/src/cswinrt/packages.config b/src/cswinrt/packages.config index 293ccb4f7..93c9c42be 100644 --- a/src/cswinrt/packages.config +++ b/src/cswinrt/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file