예제 #1
0
        private static object CoerceType(Type targetType, object value, int index, bool allowNullValueTypes)
        {
            bool isNullable = JsonReader.IsNullable(targetType);

            if (value == null)
            {
                if (allowNullValueTypes &&
                    targetType.IsValueType &&
                    !isNullable)
                {
                    throw new JsonDeserializationException(String.Format(JsonReader.ErrorNullValueType, targetType.FullName), index);
                }
                return(value);
            }

            if (isNullable)
            {
                // nullable types have a real underlying struct
                Type[] genericArgs = targetType.GetGenericArguments();
                if (genericArgs.Length == 1)
                {
                    targetType = genericArgs[0];
                }
            }

            Type actualType = value.GetType();

            if (targetType.IsAssignableFrom(actualType))
            {
                return(value);
            }

            if (targetType.IsEnum)
            {
                if (!Enum.IsDefined(targetType, value))
                {
                    // if isn't a defined value perhaps it is the JsonName
                    foreach (FieldInfo field in targetType.GetFields())
                    {
                        string jsonName = JsonNameAttribute.GetJsonName(field);
                        if (((string)value).Equals(jsonName))
                        {
                            value = field.Name;
                            break;
                        }
                    }
                }

                if (value is String)
                {
                    return(Enum.Parse(targetType, (string)value));
                }
                else
                {
                    return(Convert.ChangeType(value, targetType));
                }
            }

            if (actualType.IsArray && !targetType.IsArray)
            {
                return(JsonReader.CoerceArray(targetType, actualType, value, index, allowNullValueTypes));
            }

            if (value is String)
            {
                if (targetType == typeof(DateTime))
                {
                    DateTime date;
                    if (DateTime.TryParse(
                            (string)value,
                            DateTimeFormatInfo.InvariantInfo,
                            DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault,
                            out date))
                    {
                        return(date);
                    }
                }
                else if (targetType == typeof(Guid))
                {
                    // try-catch is pointless since will throw upon generic conversion
                    return(new Guid((string)value));
                }
                else if (targetType == typeof(Uri))
                {
                    Uri uri;
                    if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out uri))
                    {
                        return(uri);
                    }
                }
                else if (targetType == typeof(Version))
                {
                    // try-catch is pointless since will throw upon generic conversion
                    return(new Version((string)value));
                }
            }

            else if (targetType == typeof(TimeSpan))
            {
                return(new TimeSpan((long)JsonReader.CoerceType(typeof(Int64), value, index, allowNullValueTypes)));
            }

            TypeConverter converter = TypeDescriptor.GetConverter(targetType);

            if (converter.CanConvertFrom(actualType))
            {
                return(converter.ConvertFrom(value));
            }

            converter = TypeDescriptor.GetConverter(actualType);
            if (converter.CanConvertTo(targetType))
            {
                return(converter.ConvertTo(value, targetType));
            }

            return(Convert.ChangeType(value, targetType));
        }