internal object CoerceType(Type targetType, object value) { bool isNullable = TypeCoercionUtility.IsNullable(targetType); if (value == null) { if (!allowNullValueTypes && targetType.IsValueType && !isNullable) { throw new JsonTypeCoercionException(String.Format(TypeCoercionUtility.ErrorNullValueType, targetType.FullName)); } 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 (value is String) { 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; } } } return Enum.Parse(targetType, (string)value); } else { value = this.CoerceType(Enum.GetUnderlyingType(targetType), value); return Enum.ToObject(targetType, value); } } if (value is IDictionary) { Dictionary<string, MemberInfo> memberMap; return this.CoerceType(targetType, (IDictionary)value, out memberMap); } if (typeof(IEnumerable).IsAssignableFrom(targetType) && typeof(IEnumerable).IsAssignableFrom(actualType)) { return this.CoerceList(targetType, actualType, (IEnumerable)value); } 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(Char)) { if (((string)value).Length == 1) { return ((string)value)[0]; } } 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)this.CoerceType(typeof(Int64), value)); } #if !WINPHONE_8 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); } #endif try { // fall back to basics return Convert.ChangeType(value, targetType); } catch (Exception ex) { throw new JsonTypeCoercionException( String.Format("Error converting {0} to {1}", value.GetType().FullName, targetType.FullName), ex); } }
internal bool IsAssignableTo (Type c) { if (c == this) return true; if (c.IsInterface) { if (parent != null && is_created) { if (c.IsAssignableFrom (parent)) return true; } if (interfaces == null) return false; foreach (Type t in interfaces) if (c.IsAssignableFrom (t)) return true; if (!is_created) return false; } if (parent == null) return c == typeof (object); else return c.IsAssignableFrom (parent); }