コード例 #1
0
ファイル: Change.cs プロジェクト: keepingcode/framework
        private static object ConvertValue(object value, Type targetType)
        {
            Type sourceType = value?.GetType();

            if (value is Var var)
            {
                value      = var.RawValue;
                sourceType = value?.GetType();
            }

            if (value == null || value == DBNull.Value)
            {
                return(null);
            }
            if (targetType.IsAssignableFrom(sourceType))
            {
                return(value);
            }

            if (targetType == typeof(bool))
            {
                if (value is string text)
                {
                    return(text == "1" ||
                           text.Equals("true", StringComparison.InvariantCultureIgnoreCase) ||
                           text.Equals("y", StringComparison.InvariantCultureIgnoreCase) ||
                           text.Equals("yes", StringComparison.InvariantCultureIgnoreCase) ||
                           text.Equals("on", StringComparison.InvariantCultureIgnoreCase) ||
                           text.Equals("ok", StringComparison.InvariantCultureIgnoreCase) ||
                           text.Equals("sim", StringComparison.InvariantCultureIgnoreCase));
                }
                else if (sourceType.IsValueType)
                {
                    return(!value.Equals(Default.Of(sourceType)));
                }
                else
                {
                    return(System.Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture));
                }
            }

            if (targetType == typeof(string))
            {
                if (value is DateTime dateAndTime)
                {
                    if (dateAndTime.Hour == 0 &&
                        dateAndTime.Minute == 0 &&
                        dateAndTime.Second == 0 &&
                        dateAndTime.Millisecond == 0)
                    {
                        return(dateAndTime.ToString("yyyy-MM-dd"));
                    }
                    else
                    {
                        return(dateAndTime.ToString("yyyy-MM-ddTHH:mm:ss"));
                    }
                }
                else
                {
                    if (value._HasMethod("ToString", typeof(IFormatProvider)))
                    {
                        return(value._Call("ToString", CultureInfo.InvariantCulture));
                    }
                    else
                    {
                        return(value.ToString());
                    }
                }
            }

            if (targetType == typeof(Guid))
            {
                return(Guid.Parse(value.ToString()));
            }

            if (targetType == typeof(Version))
            {
                return(Version.Parse(value.ToString()));
            }

            if (targetType == typeof(DateTime) && value is string dateTime)
            {
                if (Regex.IsMatch(dateTime, @"\d{4}-\d{2}-\d{2}.*"))
                {
                    return(DateTime.Parse(dateTime, CultureInfo.InvariantCulture));
                }
            }

            if (targetType == typeof(TimeSpan))
            {
                if (value is string timeSpan && Regex.IsMatch(timeSpan, @"(\d\.)?\d{2}:\d{2}.*"))
                {
                    return(DateTime.Parse(timeSpan));
                }
                if (value is long ticks)
                {
                    return(TimeSpan.FromTicks(ticks));
                }
            }

            if (targetType == typeof(Uri))
            {
                var text = value.ToString();
                if (text.Contains(@"\"))
                {
                    text = $"file:///{text.Replace(@"\", "/")}";
                }
                else if (Regex.IsMatch(text, @"^\w:$"))
                {
                    text = $"file:///{text}/";
                }
                return(new Uri(text, UriKind.RelativeOrAbsolute));
            }

            var flags = BindingFlags.Static | BindingFlags.Public;

            var methods = sourceType.GetMethods(flags).Concat(targetType.GetMethods(flags));
            var casting = (
                from method in methods
                where method.Name == "op_Implicit" ||
                method.Name == "op_Explicit"
                where method.GetParameters().Length == 1 &&
                sourceType.IsAssignableFrom(method.GetParameters().Single().ParameterType) &&
                targetType.IsAssignableFrom(method.ReturnType)
                select method
                ).FirstOrDefault();

            if (casting != null)
            {
                var castValue = casting.Invoke(null, new[] { value });
                return(castValue);
            }

            targetType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            object convertedValue;

            if (targetType.IsEnum)
            {
                var text = value.ToString();
                if (Regex.IsMatch(text, "^[0-9, ]+$"))
                {
                    var tokens = text.Split(',', ' ').NotNullOrEmpty();
                    var number = tokens.Select(int.Parse).Sum();
                    convertedValue = Enum.ToObject(targetType, number);
                }
                else
                {
                    convertedValue = Enum.Parse(targetType, text);
                }
            }
            else
            {
                convertedValue = System.Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture);
            }

            return(convertedValue);
        }
コード例 #2
0
ファイル: Change.cs プロジェクト: keepingcode/framework
 public static object To(object value, Type targetType)
 {
     return(Convert(value, targetType, Default.Of(targetType)));
 }