Example #1
0
        // --------------------------------------------------------------------------------------------------------------------

        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);
            }
        }