public static object CreateRcwForComObject(IntPtr ptr) { if (ptr == IntPtr.Zero) { return(null); } IObjectReference identity = GetObjectReferenceForInterface(ptr).As <IUnknownVftbl>(); object keepAliveSentinel = null; Func <IntPtr, System.WeakReference <object> > rcwFactory = (_) => { object runtimeWrapper = null; if (identity.TryAs <IInspectable.Vftbl>(out var inspectableRef) == 0) { var inspectable = new IInspectable(identity); string runtimeClassName = inspectable.GetRuntimeClassName(); runtimeWrapper = TypedObjectFactoryCache.GetOrAdd(runtimeClassName, className => CreateTypedRcwFactory(className))(inspectable); } else if (identity.TryAs <ABI.WinRT.Interop.IWeakReference.Vftbl>(out var weakRef) == 0) { runtimeWrapper = new ABI.WinRT.Interop.IWeakReference(weakRef); } keepAliveSentinel = runtimeWrapper; // We don't take a strong reference on runtimeWrapper at any point, so we need to make sure it lives until it can get assigned to rcw. var runtimeWrapperReference = new System.WeakReference <object>(runtimeWrapper); var cleanupSentinel = new RuntimeWrapperCleanup(identity.ThisPtr, runtimeWrapperReference); return(runtimeWrapperReference); };
internal static bool TryGetMarshalerTypeForProjectedRuntimeClass(IObjectReference objectReference, out Type type) { if (objectReference.TryAs <IInspectable.Vftbl>(out var inspectablePtr) == 0) { rwlock.EnterReadLock(); try { IInspectable inspectable = inspectablePtr; string runtimeClassName = inspectable.GetRuntimeClassName(true); if (runtimeClassName is object) { if (ProjectedRuntimeClassNames.Contains(runtimeClassName)) { type = CustomTypeToHelperTypeMappings[CustomAbiTypeNameToTypeMappings[runtimeClassName]]; return(true); } } } finally { inspectablePtr.Dispose(); rwlock.ExitReadLock(); } } type = null; return(false); }
protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flags) { IObjectReference objRef = ComWrappersSupport.GetObjectReferenceForInterface(externalComObject); if (objRef.TryAs <IInspectable.Vftbl>(out var inspectableRef) == 0) { IInspectable inspectable = new IInspectable(inspectableRef); string runtimeClassName = inspectable.GetRuntimeClassName(noThrow: true); return(runtimeClassName switch { "Windows.Data.Text.WordSegment" => new MS.Internal.WindowsRuntime.Windows.Data.Text.WordSegment(new MS.Internal.WindowsRuntime.ABI.Windows.Data.Text.IWordSegment(objRef)), _ => inspectable });
internal static string GetRuntimeClassForTypeCreation(IInspectable inspectable, Type staticallyDeterminedType) { string runtimeClassName = inspectable.GetRuntimeClassName(noThrow: true); 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. Type implementationType = null; if (!string.IsNullOrEmpty(runtimeClassName)) { try { (implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan()); } catch (TypeLoadException) { } } if (!(implementationType != null && (staticallyDeterminedType == implementationType || staticallyDeterminedType.IsAssignableFrom(implementationType) || staticallyDeterminedType.IsGenericType && implementationType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == staticallyDeterminedType.GetGenericTypeDefinition())))) { runtimeClassName = TypeNameSupport.GetNameForType(staticallyDeterminedType, TypeNameGenerationFlags.GenerateBoxedName); } } return runtimeClassName; }