Beispiel #1
0
        /// <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>
        /// Attempts to convert the input object to the output type.
        /// </summary>
        /// <remarks>This code is an optimized version of the original Umbraco method</remarks>
        /// <param name="input">The input.</param>
        /// <param name="target">The type to convert to</param>
        /// <returns>The <see cref="Attempt{Object}"/></returns>
        public static Attempt <object> TryConvertTo(this object input, Type target)
        {
            if (target == null)
            {
                return(Attempt <object> .Fail());
            }

            try
            {
                if (input == null)
                {
                    // Nullable is ok
                    if (target.IsGenericType && GetCachedGenericNullableType(target) != null)
                    {
                        return(Attempt <object> .Succeed(null));
                    }

                    // Reference types are ok
                    return(Attempt <object> .SucceedIf(target.IsValueType == false, null));
                }

                var inputType = input.GetType();

                // Easy
                if (target == typeof(object) || inputType == target)
                {
                    return(Attempt.Succeed(input));
                }

                // Check for string so that overloaders of ToString() can take advantage of the conversion.
                if (target == typeof(string))
                {
                    return(Attempt <object> .Succeed(input.ToString()));
                }

                // If we've got a nullable of something, we try to convert directly to that thing.
                // We cache the destination type and underlying nullable types
                // Any other generic types need to fall through
                if (target.IsGenericType)
                {
                    var underlying = GetCachedGenericNullableType(target);
                    if (underlying != null)
                    {
                        // Special case for empty strings for bools/dates which should return null if an empty string.
                        if (input is string inputString)
                        {
                            //TODO: Why the check against only bool/date when a string is null/empty? In what scenario can we convert to another type when the string is null or empty other than just being null?
                            if (string.IsNullOrEmpty(inputString) && (underlying == typeof(DateTime) || underlying == typeof(bool)))
                            {
                                return(Attempt <object> .Succeed(null));
                            }
                        }

                        // Recursively call into this method with the inner (not-nullable) type and handle the outcome
                        var inner = input.TryConvertTo(underlying);

                        // And if sucessful, fall on through to rewrap in a nullable; if failed, pass on the exception
                        if (inner.Success)
                        {
                            input = inner.Result; // Now fall on through...
                        }
                        else
                        {
                            return(Attempt <object> .Fail(inner.Exception));
                        }
                    }
                }
                else
                {
                    // target is not a generic type

                    if (input is string inputString)
                    {
                        // Try convert from string, returns an Attempt if the string could be
                        // processed (either succeeded or failed), else null if we need to try
                        // other methods
                        var result = TryConvertToFromString(inputString, target);
                        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 (GetCachedCanAssign(input, inputType, target))
                    {
                        return(Attempt.Succeed(Convert.ChangeType(input, target)));
                    }
                }

                if (target == typeof(bool))
                {
                    if (GetCachedCanConvertToBoolean(inputType))
                    {
                        return(Attempt.Succeed(CustomBooleanTypeConverter.ConvertFrom(input)));
                    }
                }

                var inputConverter = GetCachedSourceTypeConverter(inputType, target);
                if (inputConverter != null)
                {
                    return(Attempt.Succeed(inputConverter.ConvertTo(input, target)));
                }

                var outputConverter = GetCachedTargetTypeConverter(inputType, target);
                if (outputConverter != null)
                {
                    return(Attempt.Succeed(outputConverter.ConvertFrom(input)));
                }

                if (target.IsGenericType && GetCachedGenericNullableType(target) != null)
                {
                    // cannot Convert.ChangeType as that does not work with nullable
                    // input has already been converted to the underlying type - just
                    // return input, there's an implicit conversion from T to T? anyways
                    return(Attempt.Succeed(input));
                }

                // Re-check convertables since we altered the input through recursion
                if (input is IConvertible convertible2)
                {
                    return(Attempt.Succeed(Convert.ChangeType(convertible2, target)));
                }
            }
            catch (Exception e)
            {
                return(Attempt <object> .Fail(e));
            }

            return(Attempt <object> .Fail());
        }
Beispiel #3
0
        /// <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());
        }
Beispiel #4
0
        /// <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);
        }