public override bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level) { var nonNullable = Binders.GetNonNullableType(toType); return(toType.IsAssignableFrom(fromType) || fromType == typeof(IronTjs.Builtins.Void) || toType == typeof(object) || toType == typeof(string) || nonNullable == typeof(bool) || Binders.IsNumber(nonNullable) && (Binders.IsNumber(fromType) || fromType == typeof(string))); }
internal static Expression TryConvertExpression(Expression expression, Type toType, ParameterExpression succeeded) { var nonNullable = Binders.GetNonNullableType(toType); if (toType == typeof(object)) { return(InSuccess(Expression.Convert(expression, toType), succeeded)); } else if (toType == expression.Type) { return(InSuccess(expression, succeeded)); } else if (expression.Type == typeof(IronTjs.Builtins.Void)) { if (toType == typeof(string)) { return(InSuccess(Expression.Constant(string.Empty), succeeded)); } else { return(InSuccess(Expression.Default(toType), succeeded)); } } else if (Binders.IsNumber(nonNullable)) { if (Binders.IsNumber(expression.Type)) { return(InSuccess(NewNullableOrThrough(Expression.Convert(expression, nonNullable), toType, nonNullable), succeeded)); } else if (expression.Type == typeof(string)) { ParameterExpression v; Expression test; if (Binders.IsInteger(nonNullable)) { v = Expression.Variable(typeof(long)); test = Expression.Call(typeof(Binders).GetMethod("TryConvertInt64"), expression, v); } else if (Binders.IsFloatingPoint(nonNullable)) { v = Expression.Variable(typeof(double)); test = Expression.Call(typeof(Binders).GetMethod("TryConvertDouble"), expression, v); } else { v = Expression.Variable(nonNullable); test = Expression.Call(nonNullable.GetMethod("TryParse", new[] { typeof(string), nonNullable.MakeByRefType() }), expression, v); } if (succeeded != null) { test = Expression.Assign(succeeded, test); } return(Expression.Block(new[] { v }, Expression.Condition(test, NewNullableOrThrough(v, toType, nonNullable), Expression.Default(toType) ) )); } } else if (toType == typeof(string)) { if (expression.Type.IsValueType) { return(InSuccess(Expression.Call(expression, expression.Type.GetMethod("ToString", Type.EmptyTypes)), succeeded)); } var v = Expression.Variable(expression.Type); return(InSuccess(Expression.Block(new[] { v }, Expression.Condition(Expression.NotEqual(Expression.Assign(v, expression), Expression.Constant(null)), Expression.Call(v, expression.Type.GetMethod("ToString", Type.EmptyTypes)), Expression.Constant("null") ) ), succeeded)); } else if (nonNullable == typeof(bool)) { Expression exp; if (Binders.IsNumber(expression.Type)) { exp = Expression.NotEqual(expression, Expression.Default(expression.Type)); } else if (expression.Type == typeof(string)) { var v = Expression.Variable(typeof(long)); exp = Expression.Block(new[] { v }, Expression.AndAlso( Expression.Call(typeof(long).GetMethod("TryParse", new[] { typeof(string), typeof(long).MakeByRefType() }), expression, v), Expression.NotEqual(v, Expression.Constant(0L)) ) ); } else if (!expression.Type.IsValueType) { exp = Expression.NotEqual(expression, Expression.Constant(null)); } else if (expression.Type.IsGenericType && expression.Type.GetGenericTypeDefinition() == typeof(Nullable <>)) { exp = Expression.Property(expression, "HasValue"); } else { return(InSuccess(nonNullable == toType ? Expression.Constant(true) : Expression.Constant(new Nullable <bool>(true)), succeeded)); } return(InSuccess(NewNullableOrThrough(exp, toType, nonNullable), succeeded)); } return(null); }
internal static object ConvertInternal(object obj, Type toType) { Type fromType; if (obj == null || (fromType = obj.GetType()) == typeof(IronTjs.Builtins.Void)) { if (toType == typeof(string)) { return(obj == null ? "null" : string.Empty); } else { return(toType.IsValueType ? toType.GetConstructor(Type.EmptyTypes).Invoke(null) : null); } } if (toType == typeof(object) || toType == fromType) { return(obj); } if (toType == typeof(string)) { return(obj.ToString()); } var nonNullableTo = Binders.GetNonNullableType(toType); if (Binders.IsNumber(nonNullableTo)) { if (Binders.IsNumber(fromType)) { var converted = System.Convert.ChangeType(obj, nonNullableTo); if (nonNullableTo == toType) { return(converted); } else { return(Activator.CreateInstance(toType, converted)); } } else if (fromType == typeof(string)) { var tryParse = nonNullableTo.GetMethod("TryParse", new[] { typeof(string), nonNullableTo.MakeByRefType() }); var argument = new[] { obj, null }; if ((bool)tryParse.Invoke(null, argument)) { if (nonNullableTo == toType) { return(argument[1]); } else { return(Activator.CreateInstance(toType, argument[1])); } } else { return(Activator.CreateInstance(toType)); } } } else if (nonNullableTo == typeof(bool)) { object converted; if (Binders.IsNumber(fromType)) { converted = System.Convert.ChangeType(obj, nonNullableTo); } else if (fromType == typeof(string)) { long value; converted = long.TryParse((string)obj, out value) && value != 0; } else if (!fromType.IsValueType) { converted = obj != null; } else if (fromType.IsGenericType && fromType.GetGenericTypeDefinition() == typeof(Nullable <>)) { converted = fromType.GetProperty("HasValue").GetValue(obj); } else { converted = true; } if (nonNullableTo == toType) { return(converted); } else { return(new Nullable <bool>((bool)converted)); } } return(NoValue); }