示例#1
0
        internal bool CanResolve(Type type, string?name)
        {
#if NETSTANDARD1_0 || NETCOREAPP1_0
            var info = type.GetTypeInfo();
#else
            var info = type;
#endif
            if (info.IsClass)
            {
                // Array could be either registered or Type can be resolved
                if (type.IsArray)
                {
                    return(IsRegistered(type, name) || CanResolve(type.GetElementType(), name));
                }

                // Type must be registered if:
                // - String
                // - Enumeration
                // - Primitive
                // - Abstract
                // - Interface
                // - No accessible constructor
                if (DelegateType.IsAssignableFrom(info) ||
                    typeof(string) == type || info.IsEnum || info.IsPrimitive || info.IsAbstract
#if NETSTANDARD1_0 || NETCOREAPP1_0
                    || !info.DeclaredConstructors.Any(c => !c.IsFamily && !c.IsPrivate))
#else
                    || !type.GetTypeInfo().DeclaredConstructors.Any(c => !c.IsFamily && !c.IsPrivate))
#endif
                { return(IsRegistered(type, name)); }

                return(true);
            }

            // Can resolve if IEnumerable or factory is registered
            if (info.IsGenericType)
            {
                var genericType = type.GetGenericTypeDefinition();

                if (genericType == typeof(IEnumerable <>) || IsRegistered(genericType, name))
                {
                    return(true);
                }
            }

            // Check if Type is registered
            return(IsRegistered(type, name));
        }
示例#2
0
        internal static bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level)
        {
            ContractUtils.RequiresNotNull(fromType, "fromType");
            ContractUtils.RequiresNotNull(toType, "toType");

            // NarrowingLevel.Zero

            if (fromType == toType)
            {
                return(true);
            }

            //  I don't want to consider boxing before numeric conversion, else I don't get the convert-int-to-long  behavior required to select Numbers.lt(long,long) over Numbers.lt(long,Object)
            //  We also need to get the narrow-long-to-int behavior required to avoid casting in host expression calls.
            //  IronRuby and IronPython both do this here:
            //if (toType.IsAssignableFrom(fromType))
            //{
            //    return true;
            //}

            // Because long[] and ulong[] are inter-assignable, we run into problems.
            // Let's just not convert from an array of one primitive type to another.

            if (fromType.IsArray && toType.IsArray && (Util.IsPrimitiveNumeric(fromType.GetElementType()) || Util.IsPrimitiveNumeric(toType.GetElementType())))
            {
                return(false);
            }

            if (!Util.IsPrimitiveNumeric(fromType) && toType.IsAssignableFrom(fromType))
            {
                return(true);
            }

            if (fromType.IsCOMObject && toType.IsInterface)
            {
                return(true); // A COM object could be cast to any interface
            }
            if (HasImplicitNumericConversion(fromType, toType))
            {
                return(true);
            }

            // try available type conversions...
            object[] tcas = toType.GetCustomAttributes(typeof(TypeConverterAttribute), true);
            foreach (TypeConverterAttribute tca in tcas)
            {
                TypeConverter tc = GetTypeConverter(tca);

                if (tc == null)
                {
                    continue;
                }

                if (tc.CanConvertFrom(fromType))
                {
                    return(true);
                }
            }

            //!!!do user-defined implicit conversions here

            if (level == NarrowingLevel.None)
            {
                return(false);
            }


            // NarrowingLevel.One

            if (WideningIntegerConversion(fromType, toType))
            {
                return(true);
            }


            if (level == NarrowingLevel.One)
            {
                return(false);
            }


            // NarrowingLevel.Two

            if (SpecialClojureConversion(fromType, toType))
            {
                return(true);
            }

            if (DelegateType.IsAssignableFrom(toType) && typeof(IFn).IsAssignableFrom(fromType))
            {
                return(true);
            }


            if (level == NarrowingLevel.Two)
            {
                return(false);
            }


            // NarrowingLevel.Three

            if (toType == typeof(bool))
            {
                return(true);
            }


            if (Util.IsPrimitiveNumeric(toType) && Util.IsPrimitiveNumeric(fromType))
            {
                return(true);
            }

            // Handle conversions of IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T
            // Similar to code in IPy's IronPython.Runtime.Converter.HasNarrowingConversion
            if (toType.IsGenericType)
            {
                Type genTo = toType.GetGenericTypeDefinition();
                if (genTo == typeof(IEnumerable <>))
                {
                    return(typeof(IEnumerable <Object>).IsAssignableFrom(fromType) || typeof(IEnumerable).IsAssignableFrom(fromType));
                }
            }

            if (level == NarrowingLevel.Three)
            {
                return(false);
            }


            // NarrowingLevel.All

            if (level < NarrowingLevel.All)
            {
                return(false);
            }

            // pick up boxing numerics here
            if (toType.IsAssignableFrom(fromType))
            {
                return(true);
            }

            // TODO: Rethink.  IPy has the following, but we get overload problems on Numbers ops
            //return HasNarrowingConversion(fromType, toType, level);

            // Handle conversions of IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T
            // Similar to code in IPy's IronPython.Runtime.Converter.HasNarrowingConversion
            if (toType.IsGenericType)
            {
                Type genTo = toType.GetGenericTypeDefinition();
                if (genTo == typeof(IList <>))
                {
                    return(typeof(IList <object>).IsAssignableFrom(fromType));
                }
                else if (genTo == typeof(Nullable <>))
                {
                    if (fromType == typeof(DynamicNull) || CanConvertFrom(fromType, toType.GetGenericArguments()[0], level))
                    {
                        return(true);
                    }
                }
                else if (genTo == typeof(IDictionary <,>))
                {
                    return(typeof(IDictionary <object, object>).IsAssignableFrom(fromType));
                }
            }

            return(false);
        }
示例#3
0
        internal static bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level)
        {
            ContractUtils.RequiresNotNull(fromType, "fromType");
            ContractUtils.RequiresNotNull(toType, "toType");

            // NarrowingLevel.Zero

            if (fromType == toType)
            {
                return(true);
            }

            //  I don't want to consider boxing before numeric conversion, else I don't get the convert-int-to-long  behavior required to select Numbers.lt(long,long) over Numbers.lt(long,Object)
            //  We also need to get the narrow-long-to-int behavior required to avoid casting in host expression calls.
            //  IronRuby and IronPython both do this here:
            //if (toType.IsAssignableFrom(fromType))
            //{
            //    return true;
            //}

            if (!Util.IsPrimitiveNumeric(fromType) && toType.IsAssignableFrom(fromType))
            {
                return(true);
            }

            if (fromType.IsCOMObject && toType.IsInterface)
            {
                return(true); // A COM object could be cast to any interface
            }
            if (HasImplicitNumericConversion(fromType, toType))
            {
                return(true);
            }

            // try available type conversions...
            object[] tcas = toType.GetCustomAttributes(typeof(TypeConverterAttribute), true);
            foreach (TypeConverterAttribute tca in tcas)
            {
                TypeConverter tc = GetTypeConverter(tca);

                if (tc == null)
                {
                    continue;
                }

                if (tc.CanConvertFrom(fromType))
                {
                    return(true);
                }
            }

            //!!!do user-defined implicit conversions here

            if (level == NarrowingLevel.None)
            {
                return(false);
            }


            // NarrowingLevel.One

            if (WideningIntegerConversion(fromType, toType))
            {
                return(true);
            }


            if (level == NarrowingLevel.One)
            {
                return(false);
            }


            // NarrowingLevel.Two

            if (SpecialClojureConversion(fromType, toType))
            {
                return(true);
            }

            if (DelegateType.IsAssignableFrom(toType) && typeof(IFn).IsAssignableFrom(fromType))
            {
                return(true);
            }


            if (level == NarrowingLevel.Two)
            {
                return(false);
            }


            // NarrowingLevel.Three

            if (toType == typeof(bool))
            {
                return(true);
            }


            if (Util.IsPrimitiveNumeric(toType) && Util.IsPrimitiveNumeric(fromType))
            {
                return(true);
            }

            if (level == NarrowingLevel.Three)
            {
                return(false);
            }


            // NarrowingLevel.All

            if (level < NarrowingLevel.All)
            {
                return(false);
            }

            // pick up boxing numerics here
            if (toType.IsAssignableFrom(fromType))
            {
                return(true);
            }

            // TODO: Rethink.  IPy has the following, but we get overload problems on Numbers ops
            //return HasNarrowingConversion(fromType, toType, level);

            return(false);
        }