diff --git a/src/WinRT.Runtime/ComWrappersSupport.cs b/src/WinRT.Runtime/ComWrappersSupport.cs index 1ab7f18b4..a97ab73ac 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.cs @@ -1,68 +1,68 @@ // Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using ABI.Microsoft.UI.Xaml.Data; -using ABI.Windows.Foundation; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; +// Licensed under the MIT License. + +using ABI.Microsoft.UI.Xaml.Data; +using ABI.Windows.Foundation; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using WinRT.Interop; - -#if NET -using ComInterfaceEntry = System.Runtime.InteropServices.ComWrappers.ComInterfaceEntry; -#endif - -#pragma warning disable 0169 // The field 'xxx' is never used -#pragma warning disable 0649 // Field 'xxx' is never assigned to, and will always have its default value - -namespace WinRT +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using WinRT.Interop; + +#if NET +using ComInterfaceEntry = System.Runtime.InteropServices.ComWrappers.ComInterfaceEntry; +#endif + +#pragma warning disable 0169 // The field 'xxx' is never used +#pragma warning disable 0649 // Field 'xxx' is never assigned to, and will always have its default value + +namespace WinRT { -#if EMBED - internal -#else - public -#endif - static partial class ComWrappersSupport - { - private readonly static ConcurrentDictionary> TypedObjectFactoryCacheForType = new ConcurrentDictionary>(); +#if EMBED + internal +#else + public +#endif + static partial class ComWrappersSupport + { + private readonly static ConcurrentDictionary> TypedObjectFactoryCacheForType = new ConcurrentDictionary>(); private readonly static ConditionalWeakTable CCWTable = new ConditionalWeakTable(); - private readonly static ConcurrentDictionary> DelegateFactoryCache = new ConcurrentDictionary>(); - - public static TReturn MarshalDelegateInvoke(IntPtr thisPtr, Func invoke) - where TDelegate : class, Delegate + private readonly static ConcurrentDictionary> DelegateFactoryCache = new ConcurrentDictionary>(); + + public static TReturn MarshalDelegateInvoke(IntPtr thisPtr, Func invoke) + where TDelegate : class, Delegate { -#if !NET - using (new Mono.ThreadContext()) -#endif - { - var target_invoke = FindObject(thisPtr); - if (target_invoke != null) - { - return invoke(target_invoke); - } - return default; - } - } - - public static void MarshalDelegateInvoke(IntPtr thisPtr, Action invoke) - where T : class, Delegate - { -#if !NET - using (new Mono.ThreadContext()) -#endif - { - var target_invoke = FindObject(thisPtr); - if (target_invoke != null) - { - invoke(target_invoke); - } - } +#if !NET + using (new Mono.ThreadContext()) +#endif + { + var target_invoke = FindObject(thisPtr); + if (target_invoke != null) + { + return invoke(target_invoke); + } + return default; + } + } + + public static void MarshalDelegateInvoke(IntPtr thisPtr, Action invoke) + where T : class, Delegate + { +#if !NET + using (new Mono.ThreadContext()) +#endif + { + var target_invoke = FindObject(thisPtr); + if (target_invoke != null) + { + invoke(target_invoke); + } + } } // If we are free threaded, we do not need to keep track of context. @@ -93,52 +93,52 @@ internal unsafe static bool IsFreeThreaded(IObjectReference objRef) } } return false; - } - - public static IObjectReference GetObjectReferenceForInterface(IntPtr externalComObject) - { - return GetObjectReferenceForInterface(externalComObject); } - public static ObjectReference GetObjectReferenceForInterface(IntPtr externalComObject) - { - if (externalComObject == IntPtr.Zero) - { - return null; - } - - ObjectReference objRef = ObjectReference.FromAbi(externalComObject); - if (IsFreeThreaded(objRef)) - { - return objRef; - } - else - { + public static IObjectReference GetObjectReferenceForInterface(IntPtr externalComObject) + { + return GetObjectReferenceForInterface(externalComObject); + } + + public static ObjectReference GetObjectReferenceForInterface(IntPtr externalComObject) + { + if (externalComObject == IntPtr.Zero) + { + return null; + } + + ObjectReference objRef = ObjectReference.FromAbi(externalComObject); + if (IsFreeThreaded(objRef)) + { + return objRef; + } + else + { using (objRef) { return new ObjectReferenceWithContext( objRef.GetRef(), Context.GetContextCallback(), Context.GetContextToken()); - } - } + } + } } - public static ObjectReference GetObjectReferenceForInterface(IntPtr externalComObject, Guid iid) - { - if (externalComObject == IntPtr.Zero) - { - return null; - } - - Marshal.ThrowExceptionForHR(Marshal.QueryInterface(externalComObject, ref iid, out IntPtr ptr)); - ObjectReference objRef = ObjectReference.Attach(ref ptr); - if (IsFreeThreaded(objRef)) - { - return objRef; - } - else - { + public static ObjectReference GetObjectReferenceForInterface(IntPtr externalComObject, Guid iid) + { + if (externalComObject == IntPtr.Zero) + { + return null; + } + + Marshal.ThrowExceptionForHR(Marshal.QueryInterface(externalComObject, ref iid, out IntPtr ptr)); + ObjectReference objRef = ObjectReference.Attach(ref ptr); + if (IsFreeThreaded(objRef)) + { + return objRef; + } + else + { using (objRef) { return new ObjectReferenceWithContext( @@ -146,51 +146,51 @@ public static ObjectReference GetObjectReferenceForInterface(IntPtr extern Context.GetContextCallback(), Context.GetContextToken(), iid); - } - } - } - + } + } + } + public static void RegisterProjectionAssembly(Assembly assembly) => TypeNameSupport.RegisterProjectionAssembly(assembly); public static void RegisterProjectionTypeBaseTypeMapping(IDictionary typeNameToBaseTypeNameMapping) => TypeNameSupport.RegisterProjectionTypeBaseTypeMapping(typeNameToBaseTypeNameMapping); - - internal static object GetRuntimeClassCCWTypeIfAny(object obj) - { - var type = obj.GetType(); - var ccwType = type.GetRuntimeClassCCWType(); - if (ccwType != null) - { - return CCWTable.GetValue(obj, obj => { - var ccwConstructor = ccwType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { type }, null); - return ccwConstructor.Invoke(new[] { obj }); - }); - } - - return obj; - } - + + internal static object GetRuntimeClassCCWTypeIfAny(object obj) + { + var type = obj.GetType(); + var ccwType = type.GetRuntimeClassCCWType(); + if (ccwType != null) + { + return CCWTable.GetValue(obj, obj => { + var ccwConstructor = ccwType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance, null, new[] { type }, null); + return ccwConstructor.Invoke(new[] { obj }); + }); + } + + return obj; + } + internal static List GetInterfaceTableEntries( #if NET6_0_OR_GREATER [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#elif NET +#elif NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] -#endif - Type type) - { +#endif + Type type) + { var entries = new List(); - bool hasCustomIMarshalInterface = false; - - if (type.IsDelegate()) - { - // Delegates have no interfaces that they implement, so adding default WinRT entries. - var helperType = type.FindHelperType(); - if (helperType is object) - { - entries.Add(new ComInterfaceEntry - { - IID = GuidGenerator.GetIID(type), - Vtable = helperType.GetAbiToProjectionVftblPtr() - }); + bool hasCustomIMarshalInterface = false; + + if (type.IsDelegate()) + { + // Delegates have no interfaces that they implement, so adding default WinRT entries. + var helperType = type.FindHelperType(); + if (helperType is object) + { + entries.Add(new ComInterfaceEntry + { + IID = GuidGenerator.GetIID(type), + Vtable = helperType.GetAbiToProjectionVftblPtr() + }); } if (ShouldProvideIReference(type)) @@ -198,8 +198,8 @@ internal static List GetInterfaceTableEntries( entries.Add(IPropertyValueEntry); entries.Add(ProvideIReference(type)); } - } - else + } + else { var objType = type.GetRuntimeClassCCWType() ?? type; var interfaces = objType.GetInterfaces(); @@ -255,42 +255,42 @@ internal static List GetInterfaceTableEntries( entries.Add(IPropertyValueEntry); entries.Add(ProvideIReferenceArray(type)); } - } - - entries.Add(new ComInterfaceEntry - { - IID = ManagedIStringableVftbl.IID, - Vtable = ManagedIStringableVftbl.AbiToProjectionVftablePtr - }); - - entries.Add(new ComInterfaceEntry - { - IID = ManagedCustomPropertyProviderVftbl.IID, - Vtable = ManagedCustomPropertyProviderVftbl.AbiToProjectionVftablePtr + } + + entries.Add(new ComInterfaceEntry + { + IID = ManagedIStringableVftbl.IID, + Vtable = ManagedIStringableVftbl.AbiToProjectionVftablePtr + }); + + entries.Add(new ComInterfaceEntry + { + IID = ManagedCustomPropertyProviderVftbl.IID, + Vtable = ManagedCustomPropertyProviderVftbl.AbiToProjectionVftablePtr + }); + + entries.Add(new ComInterfaceEntry + { + IID = ABI.WinRT.Interop.IWeakReferenceSource.IID, + Vtable = ABI.WinRT.Interop.IWeakReferenceSource.AbiToProjectionVftablePtr }); - entries.Add(new ComInterfaceEntry - { - IID = ABI.WinRT.Interop.IWeakReferenceSource.IID, - Vtable = ABI.WinRT.Interop.IWeakReferenceSource.AbiToProjectionVftablePtr - }); - - // Add IMarhal implemented using the free threaded marshaler - // to all CCWs if it doesn't already have its own. - if (!hasCustomIMarshalInterface) - { - entries.Add(new ComInterfaceEntry - { - IID = ABI.WinRT.Interop.IMarshal.IID, - Vtable = ABI.WinRT.Interop.IMarshal.Vftbl.AbiToProjectionVftablePtr - }); - } - - // Add IAgileObject to all CCWs - entries.Add(new ComInterfaceEntry - { - IID = ABI.WinRT.Interop.IAgileObject.IID, - Vtable = IUnknownVftbl.AbiToProjectionVftblPtr + // Add IMarhal implemented using the free threaded marshaler + // to all CCWs if it doesn't already have its own. + if (!hasCustomIMarshalInterface) + { + entries.Add(new ComInterfaceEntry + { + IID = ABI.WinRT.Interop.IMarshal.IID, + Vtable = ABI.WinRT.Interop.IMarshal.Vftbl.AbiToProjectionVftablePtr + }); + } + + // Add IAgileObject to all CCWs + entries.Add(new ComInterfaceEntry + { + IID = ABI.WinRT.Interop.IAgileObject.IID, + Vtable = IUnknownVftbl.AbiToProjectionVftblPtr }); entries.Add(new ComInterfaceEntry @@ -305,53 +305,57 @@ internal static List GetInterfaceTableEntries( IID = IUnknownVftbl.IID, Vtable = IUnknownVftbl.AbiToProjectionVftblPtr }); - - return entries; - } - - internal static (InspectableInfo inspectableInfo, List interfaceTableEntries) PregenerateNativeTypeInformation(Type type) - { - var interfaceTableEntries = GetInterfaceTableEntries(type); - var iids = new Guid[interfaceTableEntries.Count]; - for (int i = 0; i < interfaceTableEntries.Count; i++) - { - iids[i] = interfaceTableEntries[i].IID; - } - - if (type.FullName.StartsWith("ABI.", StringComparison.Ordinal)) - { - type = Projections.FindCustomPublicTypeForAbiType(type) ?? type.Assembly.GetType(type.FullName.Substring("ABI.".Length)) ?? type; - } - - return ( - new InspectableInfo(type, iids), - interfaceTableEntries); - } - - private static bool IsNullableT(Type implementationType) - { - return implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(System.Nullable<>); + + return entries; } - private static bool IsAbiNullableDelegate(Type implementationType) - { - return implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(ABI.System.Nullable_Delegate<>); - } - - private static bool IsIReferenceArray(Type implementationType) +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + Justification = "The existence of the ABI type implies the non-ABI type exists, as in authoring scenarios the ABI type is constructed from the non-ABI type.")] +#endif + internal static (InspectableInfo inspectableInfo, List interfaceTableEntries) PregenerateNativeTypeInformation(Type type) + { + var interfaceTableEntries = GetInterfaceTableEntries(type); + var iids = new Guid[interfaceTableEntries.Count]; + for (int i = 0; i < interfaceTableEntries.Count; i++) + { + iids[i] = interfaceTableEntries[i].IID; + } + + if (type.FullName.StartsWith("ABI.", StringComparison.Ordinal)) + { + type = Projections.FindCustomPublicTypeForAbiType(type) ?? type.Assembly.GetType(type.FullName.Substring("ABI.".Length)) ?? type; + } + + return ( + new InspectableInfo(type, iids), + interfaceTableEntries); + } + + private static bool IsNullableT(Type implementationType) + { + return implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(System.Nullable<>); + } + + private static bool IsAbiNullableDelegate(Type implementationType) + { + return implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(ABI.System.Nullable_Delegate<>); + } + + private static bool IsIReferenceArray(Type implementationType) { return implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(Windows.Foundation.IReferenceArray<>); - } - - private static Func CreateKeyValuePairFactory(Type type) - { + } + + private static Func CreateKeyValuePairFactory(Type type) + { var createRcwFunc = (Func) type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static). CreateDelegate(typeof(Func)); - return createRcwFunc; + return createRcwFunc; } - internal static Func CreateDelegateFactory(Type type) - { + internal static Func CreateDelegateFactory(Type type) + { return DelegateFactoryCache.GetOrAdd(type, (type) => { var createRcwFunc = (Func)type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static). @@ -374,10 +378,10 @@ internal static Func CreateDelegateFactory(Type type) Marshal.Release(ptr); } }; - }); - } - - private static Func CreateNullableTFactory(Type implementationType) + }); + } + + private static Func CreateNullableTFactory(Type implementationType) { var getValueMethod = implementationType.GetHelperType().GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic); return (IInspectable obj) => getValueMethod.Invoke(null, new[] { obj }); @@ -386,35 +390,35 @@ private static Func CreateNullableTFactory(Type implementa private static Func CreateAbiNullableTFactory( #if NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)] -#endif - Type implementationType) +#endif + Type implementationType) { var getValueMethod = implementationType.GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic); return (IInspectable obj) => getValueMethod.Invoke(null, new[] { obj }); } - - private static Func CreateArrayFactory(Type implementationType) + + private static Func CreateArrayFactory(Type implementationType) { var getValueFunc = (Func)implementationType.GetHelperType().GetMethod("GetValue", BindingFlags.Static | BindingFlags.NonPublic). CreateDelegate(typeof(Func)); - return getValueFunc; - } - - // This is used to hold the reference to the native value type object (IReference) until the actual value in it (boxed as an object) gets cleaned up by GC - // This is done to avoid pointer reuse until GC cleans up the boxed object - private static readonly ConditionalWeakTable _boxedValueReferenceCache = new(); - - private static Func CreateReferenceCachingFactory(Func internalFactory) - { - return inspectable => - { - object resultingObject = internalFactory(inspectable); - _boxedValueReferenceCache.Add(resultingObject, inspectable); - return resultingObject; - }; - } - - private static Func CreateCustomTypeMappingFactory(Type customTypeHelperType) + return getValueFunc; + } + + // This is used to hold the reference to the native value type object (IReference) until the actual value in it (boxed as an object) gets cleaned up by GC + // This is done to avoid pointer reuse until GC cleans up the boxed object + private static readonly ConditionalWeakTable _boxedValueReferenceCache = new(); + + private static Func CreateReferenceCachingFactory(Func internalFactory) + { + return inspectable => + { + object resultingObject = internalFactory(inspectable); + _boxedValueReferenceCache.Add(resultingObject, inspectable); + return resultingObject; + }; + } + + private static Func CreateCustomTypeMappingFactory(Type customTypeHelperType) { var fromAbiMethod = customTypeHelperType.GetMethod("FromAbi", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (fromAbiMethod is null) @@ -424,478 +428,478 @@ private static Func CreateCustomTypeMappingFactory(Type cu var fromAbiMethodFunc = (Func) fromAbiMethod.CreateDelegate(typeof(Func)); return (IInspectable obj) => fromAbiMethodFunc(obj.ThisPtr); - } - + } + internal static Func CreateTypedRcwFactory( #if NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] #endif Type implementationType, string runtimeClassName = null) - { - // If runtime class name is empty or "Object", then just use IInspectable. - if (implementationType == null || implementationType == typeof(object)) - { - // If we reach here, then we couldn't find a type that matches the runtime class name. - // Fall back to using IInspectable directly. - return (IInspectable obj) => obj; + { + // If runtime class name is empty or "Object", then just use IInspectable. + if (implementationType == null || implementationType == typeof(object)) + { + // If we reach here, then we couldn't find a type that matches the runtime class name. + // Fall back to using IInspectable directly. + return (IInspectable obj) => obj; } - if (implementationType == typeof(ABI.System.Nullable_string)) + if (implementationType == typeof(ABI.System.Nullable_string)) { - return CreateReferenceCachingFactory((IInspectable obj) => ABI.System.Nullable_string.GetValue(obj)); - } - else if (implementationType == typeof(ABI.System.Nullable_Type)) + return CreateReferenceCachingFactory((IInspectable obj) => ABI.System.Nullable_string.GetValue(obj)); + } + else if (implementationType == typeof(ABI.System.Nullable_Type)) { - return CreateReferenceCachingFactory((IInspectable obj) => ABI.System.Nullable_Type.GetValue(obj)); - } - - var customHelperType = Projections.FindCustomHelperTypeMapping(implementationType, true); - if (customHelperType != null) + return CreateReferenceCachingFactory((IInspectable obj) => ABI.System.Nullable_Type.GetValue(obj)); + } + + var customHelperType = Projections.FindCustomHelperTypeMapping(implementationType, true); + if (customHelperType != null) { return CreateReferenceCachingFactory(CreateCustomTypeMappingFactory(customHelperType)); - } - - if (implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)) - { - return CreateReferenceCachingFactory(CreateKeyValuePairFactory(implementationType)); - } - - if (implementationType.IsValueType) - { - if (IsNullableT(implementationType)) - { - return CreateReferenceCachingFactory(CreateNullableTFactory(implementationType)); - } - else - { - return CreateReferenceCachingFactory(CreateNullableTFactory(typeof(System.Nullable<>).MakeGenericType(implementationType))); - } - } + } + + if (implementationType.IsGenericType && implementationType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)) + { + return CreateReferenceCachingFactory(CreateKeyValuePairFactory(implementationType)); + } + + if (implementationType.IsValueType) + { + if (IsNullableT(implementationType)) + { + return CreateReferenceCachingFactory(CreateNullableTFactory(implementationType)); + } + else + { + return CreateReferenceCachingFactory(CreateNullableTFactory(typeof(System.Nullable<>).MakeGenericType(implementationType))); + } + } else if (IsAbiNullableDelegate(implementationType)) { return CreateReferenceCachingFactory(CreateAbiNullableTFactory(implementationType)); - } - else if (IsIReferenceArray(implementationType)) - { - return CreateReferenceCachingFactory(CreateArrayFactory(implementationType)); - } - - return CreateFactoryForImplementationType(runtimeClassName, implementationType); + } + else if (IsIReferenceArray(implementationType)) + { + return CreateReferenceCachingFactory(CreateArrayFactory(implementationType)); + } + + return CreateFactoryForImplementationType(runtimeClassName, implementationType); } -#if NET +#if NET [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] -#endif - internal static Type GetRuntimeClassForTypeCreation(IInspectable inspectable, Type staticallyDeterminedType) - { - string runtimeClassName = inspectable.GetRuntimeClassName(noThrow: true); - Type implementationType = null; - if (!string.IsNullOrEmpty(runtimeClassName)) - { +#endif + internal static Type GetRuntimeClassForTypeCreation(IInspectable inspectable, Type staticallyDeterminedType) + { + string runtimeClassName = inspectable.GetRuntimeClassName(noThrow: true); + Type implementationType = null; + if (!string.IsNullOrEmpty(runtimeClassName)) + { implementationType = TypeNameSupport.FindRcwTypeByNameCached(runtimeClassName); - } - - if (staticallyDeterminedType != null && staticallyDeterminedType != typeof(object)) - { - // We have a static type which we can use to construct the object. But, we can't just use it for all scenarios - // and primarily use it for tear off scenarios and for scenarios where runtimeclass isn't accurate. - // For instance if the static type is an interface, we return an IInspectable to represent the interface. - // But it isn't convertable back to the class via the as operator which would be possible if we use runtimeclass. - // Similarly for composable types, they can be statically retrieved using the parent class, but can then no longer - // be cast to the sub class via as operator even if it is really an instance of it per rutimeclass. - // To handle these scenarios, we use the runtimeclass if we find it is assignable to the statically determined type. - // If it isn't, we use the statically determined type as it is a tear off. - if (!(implementationType != null && - (staticallyDeterminedType == implementationType || - staticallyDeterminedType.IsAssignableFrom(implementationType) || - staticallyDeterminedType.IsGenericType && implementationType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == staticallyDeterminedType.GetGenericTypeDefinition())))) - { - return staticallyDeterminedType; - } - } - - return implementationType; - } - - private readonly static ConcurrentDictionary IsIReferenceTypeCache = new ConcurrentDictionary(); - private static bool IsIReferenceType(Type type) - { - static bool IsIReferenceTypeHelper(Type type) - { - if (type.IsDefined(typeof(WindowsRuntimeTypeAttribute)) || - WinRT.Projections.IsTypeWindowsRuntimeType(type)) - return true; - type = type.GetAuthoringMetadataType(); - if (type is object) - { - if (type.IsDefined(typeof(WindowsRuntimeTypeAttribute)) || - WinRT.Projections.IsTypeWindowsRuntimeType(type)) - return true; - } - return false; - } - - return IsIReferenceTypeCache.GetOrAdd(type, (type) => - { - if (type == typeof(string) || type.IsTypeOfType()) - return true; - if (type.IsDelegate()) - return IsIReferenceTypeHelper(type); - if (!type.IsValueType) - return false; - return type.IsPrimitive || IsIReferenceTypeHelper(type); - }); - } - - private static bool ShouldProvideIReference(Type type) => IsIReferenceType(type); - - private static ComInterfaceEntry IPropertyValueEntry => - new ComInterfaceEntry - { - IID = ManagedIPropertyValueImpl.IID, - Vtable = ManagedIPropertyValueImpl.AbiToProjectionVftablePtr - }; - - private static ComInterfaceEntry ProvideIReference(Type type) - { - if (type == typeof(int)) - { - return new ComInterfaceEntry + } + + if (staticallyDeterminedType != null && staticallyDeterminedType != typeof(object)) + { + // We have a static type which we can use to construct the object. But, we can't just use it for all scenarios + // and primarily use it for tear off scenarios and for scenarios where runtimeclass isn't accurate. + // For instance if the static type is an interface, we return an IInspectable to represent the interface. + // But it isn't convertable back to the class via the as operator which would be possible if we use runtimeclass. + // Similarly for composable types, they can be statically retrieved using the parent class, but can then no longer + // be cast to the sub class via as operator even if it is really an instance of it per rutimeclass. + // To handle these scenarios, we use the runtimeclass if we find it is assignable to the statically determined type. + // If it isn't, we use the statically determined type as it is a tear off. + if (!(implementationType != null && + (staticallyDeterminedType == implementationType || + staticallyDeterminedType.IsAssignableFrom(implementationType) || + staticallyDeterminedType.IsGenericType && implementationType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == staticallyDeterminedType.GetGenericTypeDefinition())))) + { + return staticallyDeterminedType; + } + } + + return implementationType; + } + + private readonly static ConcurrentDictionary IsIReferenceTypeCache = new ConcurrentDictionary(); + private static bool IsIReferenceType(Type type) + { + static bool IsIReferenceTypeHelper(Type type) + { + if (type.IsDefined(typeof(WindowsRuntimeTypeAttribute)) || + WinRT.Projections.IsTypeWindowsRuntimeType(type)) + return true; + type = type.GetAuthoringMetadataType(); + if (type is object) + { + if (type.IsDefined(typeof(WindowsRuntimeTypeAttribute)) || + WinRT.Projections.IsTypeWindowsRuntimeType(type)) + return true; + } + return false; + } + + return IsIReferenceTypeCache.GetOrAdd(type, (type) => + { + if (type == typeof(string) || type.IsTypeOfType()) + return true; + if (type.IsDelegate()) + return IsIReferenceTypeHelper(type); + if (!type.IsValueType) + return false; + return type.IsPrimitive || IsIReferenceTypeHelper(type); + }); + } + + private static bool ShouldProvideIReference(Type type) => IsIReferenceType(type); + + private static ComInterfaceEntry IPropertyValueEntry => + new ComInterfaceEntry + { + IID = ManagedIPropertyValueImpl.IID, + Vtable = ManagedIPropertyValueImpl.AbiToProjectionVftablePtr + }; + + private static ComInterfaceEntry ProvideIReference(Type type) + { + if (type == typeof(int)) + { + return new ComInterfaceEntry { IID = ABI.System.Nullable_int.IID, Vtable = ABI.System.Nullable_int.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(string)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_string.IID, - Vtable = ABI.System.Nullable_string.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(byte)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_byte.IID, - Vtable = ABI.System.Nullable_byte.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(short)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_short.IID, - Vtable = ABI.System.Nullable_short.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(ushort)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_ushort.IID, - Vtable = ABI.System.Nullable_ushort.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(uint)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_uint.IID, - Vtable = ABI.System.Nullable_uint.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(long)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_long.IID, - Vtable = ABI.System.Nullable_long.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(ulong)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_ulong.IID, - Vtable = ABI.System.Nullable_ulong.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(float)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_float.IID, - Vtable = ABI.System.Nullable_float.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(double)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_double.IID, - Vtable = ABI.System.Nullable_double.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(char)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_char.IID, - Vtable = ABI.System.Nullable_char.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(bool)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_bool.IID, - Vtable = ABI.System.Nullable_bool.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(Guid)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_guid.IID, - Vtable = ABI.System.Nullable_guid.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(DateTimeOffset)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_DateTimeOffset.IID, - Vtable = ABI.System.Nullable_DateTimeOffset.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(TimeSpan)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_TimeSpan.IID, - Vtable = ABI.System.Nullable_TimeSpan.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(object)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_Object.IID, - Vtable = ABI.System.Nullable_Object.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type.IsTypeOfType()) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_Type.IID, - Vtable = ABI.System.Nullable_Type.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(sbyte)) - { - return new ComInterfaceEntry - { - IID = ABI.System.Nullable_sbyte.IID, - Vtable = ABI.System.Nullable_sbyte.Vftbl.AbiToProjectionVftablePtr - }; - } - if (type.IsDelegate()) - { - var delegateHelperType = typeof(ABI.System.Nullable_Delegate<>).MakeGenericType(type); - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(delegateHelperType), - Vtable = delegateHelperType.GetAbiToProjectionVftblPtr() - }; - } - - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(ABI.System.Nullable<>).MakeGenericType(type)), - Vtable = typeof(BoxedValueIReferenceImpl<>).MakeGenericType(type).GetAbiToProjectionVftblPtr() - }; - } - - private static bool ShouldProvideIReferenceArray(Type type) - { - // Check if one dimensional array with lower bound of 0 - return type.IsArray && type == type.GetElementType().MakeArrayType() && !type.GetElementType().IsArray; - } - - private static ComInterfaceEntry ProvideIReferenceArray(Type arrayType) - { - Type type = arrayType.GetElementType(); - if (type == typeof(int)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(string)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(byte)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(short)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(ushort)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(uint)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(long)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(ulong)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(float)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(double)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(char)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(bool)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(Guid)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(DateTimeOffset)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(TimeSpan)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type == typeof(object)) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - if (type.IsTypeOfType()) - { - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), - Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr - }; - } - return new ComInterfaceEntry - { - IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray<>).MakeGenericType(type)), - Vtable = (IntPtr)typeof(BoxedArrayIReferenceArrayImpl<>).MakeGenericType(type).GetAbiToProjectionVftblPtr() - }; - } - - internal sealed class InspectableInfo - { - private readonly Lazy runtimeClassName; - - public Guid[] IIDs { get; } - public string RuntimeClassName => runtimeClassName.Value; - - internal InspectableInfo(Type type, Guid[] iids) - { - runtimeClassName = new Lazy(() => TypeNameSupport.GetNameForType(type, TypeNameGenerationFlags.GenerateBoxedName | TypeNameGenerationFlags.NoCustomTypeName)); - IIDs = iids; - } + }; + } + if (type == typeof(string)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_string.IID, + Vtable = ABI.System.Nullable_string.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(byte)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_byte.IID, + Vtable = ABI.System.Nullable_byte.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(short)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_short.IID, + Vtable = ABI.System.Nullable_short.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(ushort)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_ushort.IID, + Vtable = ABI.System.Nullable_ushort.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(uint)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_uint.IID, + Vtable = ABI.System.Nullable_uint.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(long)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_long.IID, + Vtable = ABI.System.Nullable_long.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(ulong)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_ulong.IID, + Vtable = ABI.System.Nullable_ulong.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(float)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_float.IID, + Vtable = ABI.System.Nullable_float.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(double)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_double.IID, + Vtable = ABI.System.Nullable_double.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(char)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_char.IID, + Vtable = ABI.System.Nullable_char.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(bool)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_bool.IID, + Vtable = ABI.System.Nullable_bool.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(Guid)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_guid.IID, + Vtable = ABI.System.Nullable_guid.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(DateTimeOffset)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_DateTimeOffset.IID, + Vtable = ABI.System.Nullable_DateTimeOffset.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(TimeSpan)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_TimeSpan.IID, + Vtable = ABI.System.Nullable_TimeSpan.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(object)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_Object.IID, + Vtable = ABI.System.Nullable_Object.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type.IsTypeOfType()) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_Type.IID, + Vtable = ABI.System.Nullable_Type.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(sbyte)) + { + return new ComInterfaceEntry + { + IID = ABI.System.Nullable_sbyte.IID, + Vtable = ABI.System.Nullable_sbyte.Vftbl.AbiToProjectionVftablePtr + }; + } + if (type.IsDelegate()) + { + var delegateHelperType = typeof(ABI.System.Nullable_Delegate<>).MakeGenericType(type); + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(delegateHelperType), + Vtable = delegateHelperType.GetAbiToProjectionVftblPtr() + }; + } + + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(ABI.System.Nullable<>).MakeGenericType(type)), + Vtable = typeof(BoxedValueIReferenceImpl<>).MakeGenericType(type).GetAbiToProjectionVftblPtr() + }; + } + + private static bool ShouldProvideIReferenceArray(Type type) + { + // Check if one dimensional array with lower bound of 0 + return type.IsArray && type == type.GetElementType().MakeArrayType() && !type.GetElementType().IsArray; + } + + private static ComInterfaceEntry ProvideIReferenceArray(Type arrayType) + { + Type type = arrayType.GetElementType(); + if (type == typeof(int)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(string)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(byte)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(short)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(ushort)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(uint)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(long)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(ulong)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(float)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(double)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(char)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(bool)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(Guid)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(DateTimeOffset)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(TimeSpan)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type == typeof(object)) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + if (type.IsTypeOfType()) + { + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray)), + Vtable = BoxedArrayIReferenceArrayImpl.AbiToProjectionVftablePtr + }; + } + return new ComInterfaceEntry + { + IID = global::WinRT.GuidGenerator.GetIID(typeof(IReferenceArray<>).MakeGenericType(type)), + Vtable = (IntPtr)typeof(BoxedArrayIReferenceArrayImpl<>).MakeGenericType(type).GetAbiToProjectionVftblPtr() + }; } - internal static ObjectReference CreateCCWForObject(object obj, Guid iid) - { - IntPtr ccw = CreateCCWForObjectForABI(obj, iid); - return ObjectReference.Attach(ref ccw); + internal sealed class InspectableInfo + { + private readonly Lazy runtimeClassName; + + public Guid[] IIDs { get; } + public string RuntimeClassName => runtimeClassName.Value; + + internal InspectableInfo(Type type, Guid[] iids) + { + runtimeClassName = new Lazy(() => TypeNameSupport.GetNameForType(type, TypeNameGenerationFlags.GenerateBoxedName | TypeNameGenerationFlags.NoCustomTypeName)); + IIDs = iids; + } } - internal static ObjectReferenceValue CreateCCWForObjectForMarshaling(object obj, Guid iid) - { - IntPtr ccw = CreateCCWForObjectForABI(obj, iid); - return new ObjectReferenceValue(ccw); - } - } + internal static ObjectReference CreateCCWForObject(object obj, Guid iid) + { + IntPtr ccw = CreateCCWForObjectForABI(obj, iid); + return ObjectReference.Attach(ref ccw); + } + + internal static ObjectReferenceValue CreateCCWForObjectForMarshaling(object obj, Guid iid) + { + IntPtr ccw = CreateCCWForObjectForABI(obj, iid); + return new ObjectReferenceValue(ccw); + } + } } \ No newline at end of file diff --git a/src/WinRT.Runtime/Projections.cs b/src/WinRT.Runtime/Projections.cs index 82e2f7696..7c7fef288 100644 --- a/src/WinRT.Runtime/Projections.cs +++ b/src/WinRT.Runtime/Projections.cs @@ -116,7 +116,8 @@ public static void RegisterCustomAbiTypeMapping( [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | - DynamicallyAccessedMemberTypes.PublicNestedTypes)] + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] #endif Type abiType, string winrtTypeName, @@ -139,7 +140,8 @@ private static void RegisterCustomAbiTypeMappingNoLock( [DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | - DynamicallyAccessedMemberTypes.PublicNestedTypes)] + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] #endif Type abiType, string winrtTypeName, @@ -174,7 +176,8 @@ private static void RegisterCustomAbiTypeMappingNoLock( [return: DynamicallyAccessedMembers( DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | - DynamicallyAccessedMemberTypes.PublicNestedTypes)] + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] #endif public static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRuntimeClass = false) { @@ -383,6 +386,10 @@ internal static IEnumerable GetAllPossibleTypeCombinations(IEnumerable accum, Stack stack, IEnumerable[] compatibleTypes, int index) { foreach (var type in compatibleTypes[index]) diff --git a/src/WinRT.Runtime/TypeExtensions.cs b/src/WinRT.Runtime/TypeExtensions.cs index 02683ad55..fab82c746 100644 --- a/src/WinRT.Runtime/TypeExtensions.cs +++ b/src/WinRT.Runtime/TypeExtensions.cs @@ -92,7 +92,8 @@ static Type FindHelperTypeFallback(Type type) #if NET [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | - DynamicallyAccessedMemberTypes.PublicNestedTypes)] + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] #endif public static Type GetHelperType(this Type type) { diff --git a/src/cswinrt/strings/WinRT.cs b/src/cswinrt/strings/WinRT.cs index 689882ab4..4f38e7f9e 100644 --- a/src/cswinrt/strings/WinRT.cs +++ b/src/cswinrt/strings/WinRT.cs @@ -5,6 +5,7 @@ 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; @@ -292,8 +293,12 @@ public BaseActivationFactory(string typeNamespace, string typeFullName) } moduleName = moduleName.Remove(lastSegment); } - } - + } + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091:RequiresUnreferencedCode", + Justification = "No members of the generic type are dynamically accessed in this code path.")] +#endif public unsafe ObjectReference _ActivateInstance() { IntPtr instancePtr; @@ -306,8 +311,12 @@ public unsafe ObjectReference _ActivateInstance() { MarshalInspectable.DisposeAbi(instancePtr); } - } - + } + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091:RequiresUnreferencedCode", + Justification = "No members of the generic type are dynamically accessed in this code path.")] +#endif public ObjectReference _As() => _IActivationFactory.As(); public IObjectReference _As(Guid iid) => _IActivationFactory.As(iid); } @@ -319,8 +328,17 @@ public ActivationFactory() : base(typeof(T).Namespace, typeof(T).FullName) { } static readonly ActivationFactory _factory = new ActivationFactory(); public static new I AsInterface() => _factory.Value.AsInterface(); public static ObjectReference As() => _factory._As(); - public static IObjectReference As(Guid iid) => _factory._As(iid); - public static ObjectReference ActivateInstance() => _factory._ActivateInstance(); + public static IObjectReference As(Guid iid) => _factory._As(iid); + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091:RequiresUnreferencedCode", + Justification = "No members of the generic type are dynamically accessed in this code path.")] +#endif + public static ObjectReference ActivateInstance< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.None)] +#endif + I>() => _factory._ActivateInstance(); } internal class ComponentActivationFactory : global::WinRT.Interop.IActivationFactory