/// <summary> /// Tries to convert the input object to the output type using TypeConverters. If the destination type is a superclass of the input type, /// if will use <see cref="Convert.ChangeType(object,System.Type)"/>. /// </summary> /// <param name="input">The input.</param> /// <param name="destinationType">Type of the destination.</param> /// <returns></returns> public static Attempt <object> TryConvertTo(this object input, Type destinationType) { if (input == null) { return(Attempt <object> .Fail()); } if (destinationType == typeof(object)) { return(Attempt.Succeed(input)); } if (input.GetType() == destinationType) { return(Attempt.Succeed(input)); } //check for string so that overloaders of ToString() can take advantage of the conversion. if (destinationType == typeof(string)) { return(Attempt <object> .Succeed(input.ToString())); } // if we've got a nullable of something, we try to convert directly to that thing. if (destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable <>)) { var underlyingType = Nullable.GetUnderlyingType(destinationType); //special case for empty strings for bools/dates which should return null if an empty string var asString = input as string; if (asString != null && string.IsNullOrEmpty(asString) && (underlyingType == typeof(DateTime) || underlyingType == typeof(bool))) { return(Attempt <object> .Succeed(null)); } // recursively call into myself with the inner (not-nullable) type and handle the outcome var nonNullable = input.TryConvertTo(underlyingType); // and if sucessful, fall on through to rewrap in a nullable; if failed, pass on the exception if (nonNullable.Success) { input = nonNullable.Result; // now fall on through... } else { return(Attempt <object> .Fail(nonNullable.Exception)); } } // we've already dealed with nullables, so any other generic types need to fall through if (!destinationType.IsGenericType) { if (input is string) { var result = TryConvertToFromString(input as string, destinationType); // if we processed the string (succeed or fail), we're done if (result.HasValue) { return(result.Value); } } //TODO: Do a check for destination type being IEnumerable<T> and source type implementing IEnumerable<T> with // the same 'T', then we'd have to find the extension method for the type AsEnumerable() and execute it. if (TypeHelper.IsTypeAssignableFrom(destinationType, input.GetType()) && TypeHelper.IsTypeAssignableFrom <IConvertible>(input)) { try { var casted = Convert.ChangeType(input, destinationType); return(Attempt.Succeed(casted)); } catch (Exception e) { return(Attempt <object> .Fail(e)); } } } var inputConverter = TypeDescriptor.GetConverter(input); if (inputConverter.CanConvertTo(destinationType)) { try { var converted = inputConverter.ConvertTo(input, destinationType); return(Attempt.Succeed(converted)); } catch (Exception e) { return(Attempt <object> .Fail(e)); } } if (destinationType == typeof(bool)) { var boolConverter = new CustomBooleanTypeConverter(); if (boolConverter.CanConvertFrom(input.GetType())) { try { var converted = boolConverter.ConvertFrom(input); return(Attempt.Succeed(converted)); } catch (Exception e) { return(Attempt <object> .Fail(e)); } } } var outputConverter = TypeDescriptor.GetConverter(destinationType); if (outputConverter.CanConvertFrom(input.GetType())) { try { var converted = outputConverter.ConvertFrom(input); return(Attempt.Succeed(converted)); } catch (Exception e) { return(Attempt <object> .Fail(e)); } } if (TypeHelper.IsTypeAssignableFrom <IConvertible>(input)) { try { var casted = Convert.ChangeType(input, destinationType); return(Attempt.Succeed(casted)); } catch (Exception e) { return(Attempt <object> .Fail(e)); } } return(Attempt <object> .Fail()); }
/// <summary> /// Tries to convert the input object to the output type using TypeConverters. If the destination type is a superclass of the input type, /// if will use <see cref="Convert.ChangeType(object,System.Type)"/>. /// </summary> /// <param name="input">The input.</param> /// <param name="destinationType">Type of the destination.</param> /// <returns></returns> public static Attempt <object> TryConvertTo(this object input, Type destinationType) { if (input == null) { return(Attempt <object> .False); } if (destinationType == typeof(object)) { return(new Attempt <object>(true, input)); } if (input.GetType() == destinationType) { return(new Attempt <object>(true, input)); } if (!destinationType.IsGenericType || destinationType.GetGenericTypeDefinition() != typeof(Nullable <>)) { if (TypeHelper.IsTypeAssignableFrom(destinationType, input.GetType()) && TypeHelper.IsTypeAssignableFrom <IConvertible>(input)) { var casted = Convert.ChangeType(input, destinationType); return(new Attempt <object>(true, casted)); } } var inputConverter = TypeDescriptor.GetConverter(input); if (inputConverter.CanConvertTo(destinationType)) { try { var converted = inputConverter.ConvertTo(input, destinationType); return(new Attempt <object>(true, converted)); } catch (Exception e) { return(new Attempt <object>(e)); } } if (destinationType == typeof(bool)) { var boolConverter = new CustomBooleanTypeConverter(); if (boolConverter.CanConvertFrom(input.GetType())) { try { var converted = boolConverter.ConvertFrom(input); return(new Attempt <object>(true, converted)); } catch (Exception e) { return(new Attempt <object>(e)); } } } var outputConverter = TypeDescriptor.GetConverter(destinationType); if (outputConverter.CanConvertFrom(input.GetType())) { try { var converted = outputConverter.ConvertFrom(input); return(new Attempt <object>(true, converted)); } catch (Exception e) { return(new Attempt <object>(e)); } } if (TypeHelper.IsTypeAssignableFrom <IConvertible>(input)) { try { var casted = Convert.ChangeType(input, destinationType); return(new Attempt <object>(true, casted)); } catch (Exception e) { return(new Attempt <object>(e)); } } return(Attempt <object> .False); }
/// <summary> /// Tries to convert the input object to the output type using TypeConverters. If the destination type is a superclass of the input type, /// if will use <see cref="Convert.ChangeType(object,System.Type)"/>. /// </summary> /// <param name="input">The input.</param> /// <param name="destinationType">Type of the destination.</param> /// <returns></returns> public static Attempt <object> TryConvertTo(this object input, Type destinationType) { if (input == null) { return(Attempt <object> .False); } if (destinationType == typeof(object)) { return(new Attempt <object>(true, input)); } if (input.GetType() == destinationType) { return(new Attempt <object>(true, input)); } if (!destinationType.IsGenericType || destinationType.GetGenericTypeDefinition() != typeof(Nullable <>)) { //TODO: Do a check for destination type being IEnumerable<T> and source type implementing IEnumerable<T> with // the same 'T', then we'd have to find the extension method for the type AsEnumerable() and execute it. if (TypeHelper.IsTypeAssignableFrom(destinationType, input.GetType()) && TypeHelper.IsTypeAssignableFrom <IConvertible>(input)) { try { var casted = Convert.ChangeType(input, destinationType); return(new Attempt <object>(true, casted)); } catch (Exception e) { return(new Attempt <object>(e)); } } } var inputConverter = TypeDescriptor.GetConverter(input); if (inputConverter.CanConvertTo(destinationType)) { try { var converted = inputConverter.ConvertTo(input, destinationType); return(new Attempt <object>(true, converted)); } catch (Exception e) { return(new Attempt <object>(e)); } } if (destinationType == typeof(bool)) { var boolConverter = new CustomBooleanTypeConverter(); if (boolConverter.CanConvertFrom(input.GetType())) { try { var converted = boolConverter.ConvertFrom(input); return(new Attempt <object>(true, converted)); } catch (Exception e) { return(new Attempt <object>(e)); } } } var outputConverter = TypeDescriptor.GetConverter(destinationType); if (outputConverter.CanConvertFrom(input.GetType())) { try { var converted = outputConverter.ConvertFrom(input); return(new Attempt <object>(true, converted)); } catch (Exception e) { return(new Attempt <object>(e)); } } if (TypeHelper.IsTypeAssignableFrom <IConvertible>(input)) { try { var casted = Convert.ChangeType(input, destinationType); return(new Attempt <object>(true, casted)); } catch (Exception e) { return(new Attempt <object>(e)); } } return(Attempt <object> .False); }