From 90d9954c8bdd49c89f7842257eac5972d7f1079a Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 16 Apr 2020 20:14:41 -0700 Subject: [PATCH] special casing for IReference[String] and KeyValuePair (#153) --- UnitTest/TestComponentCSharp_Tests.cs | 6 +++--- WinRT.Runtime/ComWrappersSupport.cs | 19 +++++++++++++++++++ WinRT.Runtime/IInspectable.cs | 1 + WinRT.Runtime/Projections/KeyValuePair.cs | 6 ++++++ WinRT.Runtime/TypeNameSupport.cs | 6 +++++- .../NoBuild.Targets | 2 ++ 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index ea3737422..8e6a6747a 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -126,7 +126,7 @@ public void TestKeyValuePair() TestObject.RaiseStringPairChanged(); } - [Fact(Skip = "System.ExecutionEngineException in Marshal.PtrToStructure(vftblPtr.Vftbl)")] + [Fact] public void TestObjectCasting() { var expected = new KeyValuePair("key", "value"); @@ -168,7 +168,7 @@ public void TestStringMap() } } - [Fact(Skip = "System.ExecutionEngineException in Marshal.PtrToStructure(vftblPtr.Vftbl)")] + [Fact] public void TestPropertySet() { var map = new Dictionary { ["foo"] = "bar", ["hello"] = "world" }; @@ -184,7 +184,7 @@ public void TestPropertySet() } } - [Fact(Skip = "System.ExecutionEngineException in Marshal.PtrToStructure(vftblPtr.Vftbl)")] + [Fact] public void TestValueSet() { var map = new Dictionary { ["foo"] = "bar", ["hello"] = "world" }; diff --git a/WinRT.Runtime/ComWrappersSupport.cs b/WinRT.Runtime/ComWrappersSupport.cs index 75247488a..ae5b5263f 100644 --- a/WinRT.Runtime/ComWrappersSupport.cs +++ b/WinRT.Runtime/ComWrappersSupport.cs @@ -222,6 +222,14 @@ private static bool IsIReferenceArray(Type implementationType) return implementationType.FullName.StartsWith("Windows.Foundation.IReferenceArray`1"); } + private static Func CreateKeyValuePairFactory(Type type) + { + var parms = new[] { Expression.Parameter(typeof(IInspectable), "obj") }; + return Expression.Lambda>( + Expression.Call(type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static), + parms), parms).Compile(); + } + private static Func CreateNullableTFactory(Type implementationType) { Type helperType = implementationType.GetHelperType(); @@ -252,8 +260,19 @@ private static Func CreateArrayFactory(Type implementation internal static Func CreateTypedRcwFactory(string runtimeClassName) { + // PropertySet and ValueSet can return IReference but Nullable is illegal + if (runtimeClassName == "Windows.Foundation.IReference`1") + { + return (IInspectable obj) => new ABI.System.Nullable(obj.ObjRef).Value; + } + var (implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan()); + if (implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)) + { + return CreateKeyValuePairFactory(implementationType); + } + if (implementationType.IsValueType) { if (IsNullableT(implementationType)) diff --git a/WinRT.Runtime/IInspectable.cs b/WinRT.Runtime/IInspectable.cs index c93a40406..6889131eb 100644 --- a/WinRT.Runtime/IInspectable.cs +++ b/WinRT.Runtime/IInspectable.cs @@ -91,6 +91,7 @@ public static IInspectable FromAbi(IntPtr thisPtr) => public static implicit operator IInspectable(IObjectReference obj) => obj.As(); public static implicit operator IInspectable(ObjectReference obj) => new IInspectable(obj); public ObjectReference As() => _obj.As(); + public IObjectReference ObjRef { get => _obj; } public IInspectable(IObjectReference obj) : this(obj.As()) { } public IInspectable(ObjectReference obj) { diff --git a/WinRT.Runtime/Projections/KeyValuePair.cs b/WinRT.Runtime/Projections/KeyValuePair.cs index f7987bb9c..66132fdea 100644 --- a/WinRT.Runtime/Projections/KeyValuePair.cs +++ b/WinRT.Runtime/Projections/KeyValuePair.cs @@ -36,6 +36,12 @@ public static IObjectReference CreateMarshaler(global::System.Collections.Generi public static IntPtr GetAbi(IObjectReference objRef) => objRef?.ThisPtr ?? IntPtr.Zero; + public static object CreateRcw(IInspectable obj) + { + var pair = new KeyValuePair(obj.As()); + return (object)new global::System.Collections.Generic.KeyValuePair(pair.Key, pair.Value); + } + public static global::System.Collections.Generic.KeyValuePair FromAbi(IntPtr thisPtr) { var pair = new KeyValuePair(KeyValuePair._FromAbi(thisPtr)); diff --git a/WinRT.Runtime/TypeNameSupport.cs b/WinRT.Runtime/TypeNameSupport.cs index 16609e7f7..ae2d8e512 100644 --- a/WinRT.Runtime/TypeNameSupport.cs +++ b/WinRT.Runtime/TypeNameSupport.cs @@ -148,7 +148,11 @@ private static (string genericTypeName, Type[] genericTypes, int remaining) Pars continue; } else if (remainingTypeName[0] == '>') - { + { + // Skip the space after nested '>' + var skip = (remainingTypeName.Length > 1 && remainingTypeName[1] == ' ') ? 2 : 1; + remainingIndex += skip; + remainingTypeName = remainingTypeName.Slice(skip); break; } else diff --git a/WinUI/WinUIDesktopSample.Package/NoBuild.Targets b/WinUI/WinUIDesktopSample.Package/NoBuild.Targets index 35c6b94d9..c662886c9 100644 --- a/WinUI/WinUIDesktopSample.Package/NoBuild.Targets +++ b/WinUI/WinUIDesktopSample.Package/NoBuild.Targets @@ -5,4 +5,6 @@ project from the command line. --> + + \ No newline at end of file