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);
            };
Example #2
0
 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);
 }
Example #3
0
        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
                });
Example #4
0
        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;
        }