Exemplo n.º 1
0
        /// <summary>Verify COM interface is OK, return it's GUID value.</summary>
        public static Guid checkInterface(Type tp)
        {
            if (!tp.IsInterface)
            {
                throw new ArgumentException($"Marshaler type argument { tp.FullName } is not an interface");
            }

            if (!tp.IsPublic)
            {
                // Proxies are implemented in different assembly, a dynamic one, they need access to the interface
                throw new ArgumentException($"COM interface { tp.FullName } is not public");
            }

            if (tp.IsGenericType || tp.IsConstructedGenericType)
            {
                throw new ArgumentException($"COM interface { tp.FullName } is generic, this is not supported");
            }

            ComInterfaceAttribute attribute = tp.GetCustomAttribute <ComInterfaceAttribute>();

            if (null == attribute)
            {
                throw new ArgumentException($"COM interface { tp.FullName } doesn't have [ComInterface] attribute applied");
            }

            foreach (var m in tp.GetMethods())
            {
                ParamsMarshalling.checkInterfaceMethod(m);
            }

            return(attribute.iid);
        }
Exemplo n.º 2
0
        /// <summary>Cast the object to another COM interface</summary>
        /// <typeparam name="I">Result COM interface</typeparam>
        /// <param name="obj">The object to cast</param>
        /// <param name="releaseOldOne">If true, and the argument is a C++ implemented object, this method will release the old one.</param>
        /// <returns>The object casted to the requested COM interface</returns>
        public static I cast <I>(object obj, bool releaseOldOne = false) where I : class
        {
            var type = typeof(I);

            if (!type.IsInterface)
            {
                throw new InvalidCastException("The type argument of the cast method must be an interface");
            }
            ComInterfaceAttribute attribute = type.GetCustomAttribute <ComInterfaceAttribute>();

            if (null == attribute)
            {
                throw new InvalidCastException("The type argument of the cast method must be an interface with [ComInterface] custom attribute");
            }

            if (null == obj)
            {
                return(null);
            }

            if (obj is RuntimeClass runtimeClass)
            {
                // C++ implemented COM object
                if (obj is I result)
                {
                    // The proxy already implements the interface. We're probably casting to a base interface.
                    return(result);
                }

                IntPtr newPointer;
                try
                {
                    newPointer = runtimeClass.queryInterface(attribute.iid, true);
                }
                catch (Exception ex)
                {
                    throw new InvalidCastException("Unable to cast, the native object doesn't support the interface", ex);
                }
                finally
                {
                    if (releaseOldOne)
                    {
                        ((IDisposable)runtimeClass).Dispose();
                    }
                }

                try
                {
                    return((I)NativeWrapper.wrap(type, newPointer));
                }
                catch (Exception ex)
                {
                    runtimeClass.release();
                    throw new InvalidCastException("Unable to cast, something's wrong with the interface", ex);
                }
            }

            if (obj is ManagedObject managedObject)
            {
                // C# implemented COM object
                if (managedObject.managed is I result)
                {
                    return(result);
                }

                throw new InvalidCastException($"{ managedObject.managed.GetType().FullName } doesn't implement interface { type.FullName }");
            }

            throw new InvalidCastException($"{ obj.GetType().FullName } is not a ComLight object");
        }