public void CoerceType_DictionaryToExpando_CoercesViaDictionaryCopy() { var input = new Hashtable { { "One", 1 }, { "Two", 2 }, { "Three", 3 }, { "Four", 4 } }; dynamic expected = new ExpandoObject(); expected.One = 1; expected.Two = 2; expected.Three = 3; expected.Four = 4; var settings = new DataReaderSettings(); var actual = new TypeCoercionUtility(settings, settings.AllowNullValueTypes).CoerceType(expected.GetType(), input); Assert.Equal(expected, actual); }
public void CoerceType_ExpandoToGenericDictionary_CoercesViaGenericDictionaryCopy() { dynamic input = new ExpandoObject(); input.One = 1; input.Two = 2; input.Three = 3; input.Four = 4; var expected = new Dictionary <string, object> { { "One", 1 }, { "Two", 2 }, { "Three", 3 }, { "Four", 4 } }; var settings = new DataReaderSettings(); var actual = new TypeCoercionUtility(settings, settings.AllowNullValueTypes).CoerceType(typeof(Dictionary <string, object>), input); Assert.Equal(expected, actual); }
public void CoerceType_ListToArray_CoercesViaListCtor() { var input = new List <string> { "One", "Two", "Three", "Four" }; var expected = new string[] { "One", "Two", "Three", "Four" }; var settings = new DataReaderSettings(); var actual = new TypeCoercionUtility(settings, settings.AllowNullValueTypes).CoerceType(expected.GetType(), input); Assert.Equal(expected, actual); }
private object CoerceList(Type targetType, Type valueType, IEnumerable value) { targetType = TypeCoercionUtility.ResolveInterfaceType(targetType); if (targetType.IsArray) { // arrays are much simpler to create return(this.CoerceArray(targetType.GetElementType(), value)); } // targetType serializes as a JSON array but is not an array // assume is an ICollection or IEnumerable with AddRange, Add, // or custom Constructor with which we can populate it FactoryMap factory = this.ResolverCache.LoadFactory(targetType); if (factory == null) { throw new TypeCoercionException(String.Format( TypeCoercionUtility.ErrorCtor, targetType.FullName)); } foreach (Type argType in factory.ArgTypes) { if (argType.IsAssignableFrom(valueType)) { try { // invoke first constructor that can take this value as an argument return(factory[argType](value)); } catch { // there might exist a better match continue; } } } if (factory.Ctor == null) { throw new TypeCoercionException(String.Format( TypeCoercionUtility.ErrorCtor, targetType.FullName)); } // attempt bulk insert first as is most efficient if (factory.AddRange != null && factory.AddRangeType != null && factory.AddRangeType.IsAssignableFrom(valueType)) { object collection = factory.Ctor(); factory.AddRange(collection, value); return(collection); } // attempt sequence of single inserts next if (factory.Add != null && factory.AddType != null) { object collection = factory.Ctor(); Type addType = factory.AddType; // loop through adding items to collection foreach (object item in value) { factory.Add(collection, this.CoerceType(addType, item)); } return(collection); } try { // finally fall back to basics return(Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture)); } catch (Exception ex) { throw new TypeCoercionException( String.Format( "Error converting {0} to {1}", value.GetType().FullName, targetType.FullName), ex); } }
/// <summary> /// Coerces the object value to Type of <paramref name="targetType"/> /// </summary> /// <param name="targetType"></param> /// <param name="value"></param> /// <returns></returns> public object CoerceType(Type targetType, object value) { if (targetType == null || targetType == typeof(object)) { return(value); } bool isNullable = TypeCoercionUtility.IsNullable(targetType); if (value == null) { // TODO: validate that this is what we want if (!this.AllowNullValueTypes && targetType.IsValueType && !isNullable) { throw new TypeCoercionException(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)) { IDictionary <string, MemberMap> maps = this.ResolverCache.LoadMaps(targetType); if (maps != null && maps.ContainsKey((string)value)) { value = maps[(string)value].Name; } } return(Enum.Parse(targetType, (string)value, false)); } else { value = this.CoerceType(Enum.GetUnderlyingType(targetType), value); return(Enum.ToObject(targetType, value)); } } if (value is IDictionary <string, object> ) { return(this.CoerceType(targetType, (IDictionary <string, object>)value)); } else if (value is IDictionary) { return(this.CoerceType(targetType, (IDictionary)value)); } 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; try{ date = DateTime.Parse( (string)value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault); if (date.Kind == DateTimeKind.Local) { return(date.ToUniversalTime()); } return(date); }catch (Exception) {} if (JsonFx.Model.Filters.MSAjaxDateFilter.TryParseMSAjaxDate( (string)value, 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)) { try{ return(TimeSpan.FromTicks(Int64.Parse((string)value))); }catch (Exception) {} try{ return(TimeSpan.Parse((string)value)); }catch (Exception) {} } } else if (targetType == typeof(TimeSpan)) { return(new TimeSpan((long)this.CoerceType(typeof(Int64), value))); } #if !SILVERLIGHT 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, CultureInfo.InvariantCulture)); } catch (Exception ex) { throw new TypeCoercionException( String.Format( "Error converting {0} to {1}", value.GetType().FullName, targetType.FullName), ex); } }
/// <summary> /// Instantiates a new instance of objectType. /// </summary> /// <param name="objectType"></param> /// <returns>objectType instance</returns> internal object InstantiateObject(Type targetType, object args) { targetType = TypeCoercionUtility.ResolveInterfaceType(targetType); FactoryMap factory = this.ResolverCache.LoadFactory(targetType); if ((factory == null) || (factory.Ctor == null)) { throw new TypeCoercionException(String.Format( TypeCoercionUtility.ErrorCtor, targetType.FullName)); } if ((factory.CtorArgs == null) || (factory.CtorArgs.Length < 1)) { // default constructor return(factory.Ctor()); } object[] ctorArgs = new object[factory.CtorArgs.Length]; IDictionary <string, object> genericArgs = args as IDictionary <string, object>; if (genericArgs != null) { for (int i = 0, length = ctorArgs.Length; i < length; i++) { string name = factory.CtorArgs[i].Name; Type type = factory.CtorArgs[i].ParameterType; foreach (string key in genericArgs.Keys) { try { if (StringComparer.OrdinalIgnoreCase.Equals(key, name)) { ctorArgs[i] = this.CoerceType(type, genericArgs[key]); break; } } catch { } } } } else { IDictionary otherArgs = args as IDictionary; if (otherArgs != null) { for (int i = 0, length = ctorArgs.Length; i < length; i++) { string name = factory.CtorArgs[i].Name; Type type = factory.CtorArgs[i].ParameterType; foreach (string key in otherArgs.Keys) { try { if (StringComparer.OrdinalIgnoreCase.Equals(key, name)) { ctorArgs[i] = this.CoerceType(type, otherArgs[key]); break; } } catch { } } } } } // use a custom constructor return(factory.Ctor(ctorArgs)); }