Example #1
0
        public static bool IsAssignableFrom(TypeOnStack type1, TypeOnStack type2)
        {
            // voids aren't assignable
            if (type1.IsVoid || type2.IsVoid)
            {
                return(false);
            }

            // wildcards match *everything*
            if (type1 == TypeOnStack.Get <WildcardType>() || type2 == TypeOnStack.Get <WildcardType>())
            {
                return(true);
            }

            if (type1.IsArray && type2.IsArray)
            {
                if (type1.Type.GetArrayRank() == type2.Type.GetArrayRank())
                {
                    var t1Elem = type1.Type.GetElementType();
                    var t2Elem = type2.Type.GetElementType();

                    while (t1Elem.HasElementType)
                    {
                        t1Elem = t1Elem.GetElementType();
                    }
                    while (t2Elem.HasElementType)
                    {
                        t2Elem = t2Elem.GetElementType();
                    }

                    if (t1Elem == typeof(WildcardType) || t2Elem == typeof(WildcardType))
                    {
                        return(true);
                    }
                }
            }

            if (type1.IsPointer && type2.IsPointer)
            {
                if (type1.Type.GetElementType() == typeof(WildcardType) || type2.Type.GetElementType() == typeof(WildcardType))
                {
                    return(true);
                }
            }

            if (type1.IsReference && type2.IsReference)
            {
                if (type1.Type.GetElementType() == typeof(WildcardType) || type2.Type.GetElementType() == typeof(WildcardType))
                {
                    return(true);
                }
            }

            // any pointer type matches, well, any pointer
            if (type1.Type == typeof(AnyPointerType) && type2.IsPointer)
            {
                return(true);
            }
            if (type2.Type == typeof(AnyPointerType) && type1.IsPointer)
            {
                return(true);
            }

            // likewise for any by ref
            if (type1.Type == typeof(AnyByRefType) && type2.IsReference)
            {
                return(true);
            }
            if (type2.Type == typeof(AnyByRefType) && type1.IsReference)
            {
                return(true);
            }

            // Native int can be convereted to any pointer type
            if (type1.IsPointer && type2 == TypeOnStack.Get <NativeIntType>())
            {
                return(true);
            }
            if (type2.IsPointer && type1 == TypeOnStack.Get <NativeIntType>())
            {
                return(true);
            }

            if ((type1.IsPointer || type1.IsReference) && !(type2.IsPointer || type2.IsReference))
            {
                return(false);
            }
            if ((type2.IsPointer || type2.IsReference) && !(type1.IsPointer || type1.IsReference))
            {
                return(false);
            }

            if (type1.IsPointer || type1.IsReference)
            {
                return(type1.Type.GetElementType() == type2.Type.GetElementType());
            }

            var t1 = type1.Type;
            var t2 = type2.Type;


            // The null type can be assigned to any reference type
            if (t1 == typeof(NullType) && !TypeHelpers.IsValueType(t2))
            {
                return(true);
            }
            if (t2 == typeof(NullType) && !TypeHelpers.IsValueType(t1))
            {
                return(true);
            }

            t1 = Alias(t1);
            t2 = Alias(t2);

            return(ReallyIsAssignableFrom(t1, t2));
        }
Example #2
0
        private static bool ReallyIsAssignableFrom(Type t1, Type t2)
        {
            if (t1 == t2)
            {
                return(true);
            }

            if (t1 == typeof(OnlyObjectType))
            {
                if (t2 == typeof(object))
                {
                    return(true);
                }

                return(false);
            }

            // quick and dirty base case
            if (t1 == typeof(object) && !TypeHelpers.IsValueType(t2))
            {
                return(true);
            }

            // you have to box in this case
            if (t1 == typeof(object) && TypeHelpers.IsValueType(t2))
            {
                return(false);
            }

            var t1Bases = GetBases(t1);
            var t2Bases = GetBases(t2);

            if (t2Bases.Any(t2b => TypeOnStack.Get(t1).IsAssignableFrom(TypeOnStack.Get(t2b))))
            {
                return(true);
            }

            if (TypeHelpers.IsInterface(t1))
            {
                var t2Interfaces = (LinqArray <Type>)t2.GetInterfaces();

                return(t2Interfaces.Any(t2i => TypeOnStack.Get(t1).IsAssignableFrom(TypeOnStack.Get(t2i))));
            }

            if (TypeHelpers.IsGenericType(t1) && TypeHelpers.IsGenericType(t2))
            {
                var t1Def = t1.GetGenericTypeDefinition();
                var t2Def = t2.GetGenericTypeDefinition();

                if (t1Def != t2Def)
                {
                    return(false);
                }

                var t1Args = t1.GetGenericArguments();
                var t2Args = t2.GetGenericArguments();

                for (var i = 0; i < t1Args.Length; i++)
                {
                    if (!TypeOnStack.Get(t1Args[i]).IsAssignableFrom(TypeOnStack.Get(t2Args[i])))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            try
            {
                return(t1.IsAssignableFrom(t2));
            }
            catch (NotSupportedException)
            {
                // Builders, some generic types, and so on don't implement this; just assume it's *no good* for now
                return(false);
            }
        }