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)); }
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); }
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); }