// -------------------------------------------------------------------------------------------------------------------- public static object ChangeType(object value, Type targetType, IFormatProvider provider = null) { if (targetType == null) { throw new ArgumentNullException("targetType"); } if (value == DBNull.Value) { value = null; } var valueType = value != null?value.GetType() : typeof(object); if (valueType == targetType || targetType.IsAssignableFrom(valueType)) { return(value); // (same type as target! [or at least compatible]) } if (provider == null) { provider = Thread.CurrentThread.CurrentCulture; } var targetUnderlyingType = Nullable.GetUnderlyingType(targetType); if (targetUnderlyingType != null) { if (value == null) { return(value); } // ... this is a nullable type target, so need to convert to underlying type first, then to a nullable type ... value = ChangeType(value, targetUnderlyingType, provider); // (recursive call to convert to the underlying nullable type) return(Activator.CreateInstance(targetType, value)); } else if (targetType == typeof(string)) { return(value != null?value.ToString() : ""); } else if (targetType == typeof(Boolean)) { if (value == null || value is string && ((string)value).IsNullOrWhiteSpace()) // (null or empty strings will be treated as 'false', but explicit text will try to be converted) { value = false; } else if (Utilities.IsNumeric(valueType)) { value = Convert.ToDouble(value) != 0; // (assume any value other than 0 is true) } else if ((value = Utilities.ToBoolean(value, null)) == null) { throw new InvalidCastException(string.Format("Types.ChangeType(): Cannot convert string value \"{0}\" to a Boolean.", value)); } return(value); // (this has the correct type already, so just return now) } else if (targetType.IsValueType && targetType.IsPrimitive) { if (value == null || value is string && ((string)value).IsNullOrWhiteSpace()) { // ... cannot set values to 'null' or empty strings, so translate this to a value type before conversion ... if (targetType == typeof(bool)) { value = false; } else if (targetType == typeof(DateTime)) { value = DateTime.MinValue; } else { value = 0; } } else if (value is string) { // ... a value type is expected, but 'value' is a string, so try converting the string to a number value first in preparation ... double d; if (double.TryParse((string)value, System.Globalization.NumberStyles.Any, provider, out d)) { value = d; } } } else if (value == null) { return(null); } try { return(Convert.ChangeType(value, targetType, provider)); } catch (Exception ex) { throw new InvalidCastException(string.Format("Types.ChangeType(): Cannot convert value \"{0}\" (type: '{1}') to type '{2}'. If you are developing the source type yourself, implement the 'IConvertible' interface.", Utilities.ND(value, ""), value.GetType().FullName, targetType.FullName), ex); } }