Пример #1
0
        public override bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level)
        {
            var nonNullable = Binders.GetNonNullableType(toType);

            return(toType.IsAssignableFrom(fromType) ||
                   fromType == typeof(Builtins.Void) ||
                   toType == typeof(object) ||
                   toType == typeof(string) ||
                   nonNullable == typeof(bool) ||
                   Binders.IsNumber(nonNullable) && (Binders.IsNumber(fromType) || fromType == typeof(string)));
        }
Пример #2
0
        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(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 bool?(true)), succeeded));
                }
                return(InSuccess(NewNullableOrThrough(exp, toType, nonNullable), succeeded));
            }
            return(null);
        }
Пример #3
0
        internal static object ConvertInternal(object obj, Type toType)
        {
            Type fromType;

            if (obj == null || (fromType = obj.GetType()) == typeof(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 bool?((bool)converted));
                }
            }
            return(NoValue);
        }