Example #1
0
        /// <summary>
        /// Gets a list of interfaces implemented by <paramref name="type"/> that aren't inherited by any other shadowed interfaces.
        /// </summary>
        /// <param name="type">The type for which to get the list.</param>
        /// <returns>The interface list.</returns>
        private static List <Type> GetUninheritedShadowedInterfaces(Type type)
        {
            // Cache reflection on interface inheritance
            lock (typeToShadowTypes)
            {
                if (!typeToShadowTypes.TryGetValue(type, out List <Type> cachedInterfaces))
                {
                    var interfaces = type.GetTypeInfo().ImplementedInterfaces.ToList();
                    typeToShadowTypes.Add(type, interfaces);

                    var interfacesToRemove = new List <Type>();

                    // First pass to identify most detailed interfaces
                    foreach (var item in interfaces)
                    {
                        // Only process interfaces that are using shadow
                        var shadowAttribute = ShadowAttribute.Get(item);
                        if (shadowAttribute == null)
                        {
                            interfacesToRemove.Add(item);
                            continue;
                        }

                        // Keep only final interfaces and not intermediate.
                        var inheritList = item.GetTypeInfo().ImplementedInterfaces;
                        foreach (var inheritInterface in inheritList)
                        {
                            interfacesToRemove.Add(inheritInterface);
                        }
                    }

                    foreach (var toRemove in interfacesToRemove)
                    {
                        interfaces.Remove(toRemove);
                    }
                    return(interfaces);
                }
                return(cachedInterfaces);
            }
        }
        internal void Initialize(ICallbackable callbackable)
        {
            callbackable.Shadow = this;

            var         type = callbackable.GetType();
            List <Type> slimInterfaces;

            // Cache reflection on COM interface inheritance
            lock (typeToShadowTypes)
            {
                if (!typeToShadowTypes.TryGetValue(type, out slimInterfaces))
                {
#if NET40
                    var interfaces = type.GetTypeInfo().GetInterfaces();
#else
                    var interfaces = type.GetTypeInfo().ImplementedInterfaces;
#endif
                    slimInterfaces = new List <Type>();
                    slimInterfaces.AddRange(interfaces);
                    typeToShadowTypes.Add(type, slimInterfaces);

                    // First pass to identify most detailed interfaces
                    foreach (var item in interfaces)
                    {
                        // Only process interfaces that are using shadow
                        var shadowAttribute = ShadowAttribute.Get(item);
                        if (shadowAttribute == null)
                        {
                            slimInterfaces.Remove(item);
                            continue;
                        }

                        // Keep only final interfaces and not intermediate.
#if NET40
                        var inheritList = item.GetTypeInfo().GetInterfaces();
#else
                        var inheritList = item.GetTypeInfo().ImplementedInterfaces;
#endif
                        foreach (var inheritInterface in inheritList)
                        {
                            slimInterfaces.Remove(inheritInterface);
                        }
                    }
                }
            }

            CppObjectShadow iunknownShadow = null;

            // Second pass to instantiate shadow
            foreach (var item in slimInterfaces)
            {
                // Only process interfaces that are using shadow
                var shadowAttribute = ShadowAttribute.Get(item);

                // Initialize the shadow with the callback
                var shadow = (CppObjectShadow)Activator.CreateInstance(shadowAttribute.Type);
                shadow.Initialize(callbackable);

                // Take the first shadow as the main IUnknown
                if (iunknownShadow == null)
                {
                    iunknownShadow = shadow;
                    // Add IUnknown as a supported interface
                    guidToShadow.Add(ComObjectShadow.IID_IUnknown, iunknownShadow);
                }

                guidToShadow.Add(Utilities.GetGuidFromType(item), shadow);

                // Associate also inherited interface to this shadow
#if NET40
                var inheritList = item.GetTypeInfo().GetInterfaces();
#else
                var inheritList = item.GetTypeInfo().ImplementedInterfaces;
#endif
                foreach (var inheritInterface in inheritList)
                {
                    var inheritShadowAttribute = ShadowAttribute.Get(inheritInterface);
                    if (inheritShadowAttribute == null)
                    {
                        continue;
                    }

                    // Use same shadow as derived
                    guidToShadow.Add(Utilities.GetGuidFromType(inheritInterface), shadow);
                }
            }

            // Precalculate the list of GUID without IUnknown and IInspectable
            // Used for WinRT
            int countGuids = 0;
            foreach (var guidKey in guidToShadow.Keys)
            {
                if (guidKey != Utilities.GetGuidFromType(typeof(IInspectable)) && guidKey != Utilities.GetGuidFromType(typeof(IUnknown)))
                {
                    countGuids++;
                }
            }

            guidPtr = Marshal.AllocHGlobal(Utilities.SizeOf <Guid>() * countGuids);
            Guids   = new IntPtr[countGuids];
            int i = 0;
            unsafe
            {
                var pGuid = (Guid *)guidPtr;
                foreach (var guidKey in guidToShadow.Keys)
                {
                    if (guidKey == Utilities.GetGuidFromType(typeof(IInspectable)) || guidKey == Utilities.GetGuidFromType(typeof(IUnknown)))
                    {
                        continue;
                    }

                    pGuid[i] = guidKey;
                    // Store the pointer
                    Guids[i] = new IntPtr(pGuid + i);
                    i++;
                }
            }
        }
Example #3
0
        internal ShadowContainer(ICallbackable callbackable)
        {
            var type = callbackable.GetType();

            var guidList = new List <Guid>();

            // Associate all shadows with their interfaces.
            foreach (var item in GetUninheritedShadowedInterfaces(type))
            {
                var shadowAttribute = ShadowAttribute.Get(item);

                // Initialize the shadow with the callback
                var shadow = (CppObjectShadow)Activator.CreateInstance(shadowAttribute.Type);
                shadow.Initialize(callbackable);

                guidToShadow.Add(item.GetTypeInfo().GUID, shadow);
                if (item.GetTypeInfo().GetCustomAttribute <ExcludeFromTypeListAttribute>() != null)
                {
                    guidList.Add(item.GetTypeInfo().GUID);
                }

                // Associate also inherited interface to this shadow
                var inheritList = item.GetTypeInfo().ImplementedInterfaces;

                foreach (var inheritInterface in inheritList)
                {
                    // If there isn't a Shadow attribute then this isn't a native interface.
                    var inheritShadowAttribute = ShadowAttribute.Get(inheritInterface);
                    if (inheritShadowAttribute == null)
                    {
                        continue;
                    }

                    // If we have the same GUID as an already added interface,
                    // then there's already an accurate shadow for it, so we have nothing to do.
                    if (guidToShadow.ContainsKey(inheritInterface.GetTypeInfo().GUID))
                    {
                        continue;
                    }

                    // Use same shadow as derived
                    guidToShadow.Add(inheritInterface.GetTypeInfo().GUID, shadow);
                    if (inheritInterface.GetTypeInfo().GetCustomAttribute <ExcludeFromTypeListAttribute>() != null)
                    {
                        guidList.Add(inheritInterface.GetTypeInfo().GUID);
                    }
                }
            }

            var guidCount = guidList.Count;

            Guids = new IntPtr[guidCount];

            guidPtr = Marshal.AllocHGlobal(Unsafe.SizeOf <Guid>() * guidCount);

            unsafe
            {
                var i     = 0;
                var pGuid = (Guid *)guidPtr;
                foreach (var guidKey in guidList)
                {
                    pGuid[i] = guidKey;
                    // Store the pointer
                    Guids[i] = new IntPtr(pGuid + i);
                    i++;
                }
            }
        }