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); }
public static object To(object value, Type targetType) { return(Convert(value, targetType, Default.Of(targetType))); }