private static object SantizeValue(object value, PropertyMapInfo info) { bool propertyIsCastableEnumerable = info.IsCastableEnumerableType; bool propertyIsConvertableEnumerable = info.IsConvertableEnumerableType; if (value != null) { Type valueType = value.GetType(); if (valueType == info.PropertyType) { return(value); } bool valueIsConvertableEnumerable = valueType.IsConvertableEnumerableType(); // You cannot set an enumerable of type from an empty object array. // This should allow the casting back of IEnumerable<T> to an empty List<T> Collection<T> etc. // I cant think of any that don't have an empty constructor if (value.Equals(Enumerable.Empty <object>()) && propertyIsCastableEnumerable) { Type typeArg = info.PropertyType.GetTypeInfo().GenericTypeArguments.First(); return(info.PropertyType.IsInterface ? EnumerableInvocations.Cast(typeArg, (IEnumerable)value) : info.PropertyType.GetInstance()); } // Ensure only a single item is returned when requested. if (valueIsConvertableEnumerable && !propertyIsConvertableEnumerable) { // Property is not enumerable, but value is, so grab first item IEnumerator enumerator = ((IEnumerable)value).GetEnumerator(); return(enumerator.MoveNext() ? enumerator.Current : null); } // And now check for the reverse situation. if (!valueIsConvertableEnumerable && propertyIsConvertableEnumerable) { var array = Array.CreateInstance(value.GetType(), 1); array.SetValue(value, 0); return(array); } } else { if (propertyIsCastableEnumerable) { if (info.PropertyType.IsInterface && !info.IsEnumerableOfKeyValueType) { // Value is null, but property is enumerable interface, so return empty enumerable return(EnumerableInvocations.Empty(info.PropertyType.GenericTypeArguments.First())); } // Concrete enumerables cannot be cast from Array so we create an instance and return it // if we know it has an empty constructor. ParameterInfo[] constructorParams = info.PropertyType.GetConstructorParameters(); if (constructorParams != null && constructorParams.Length == 0) { // Internally this uses Activator.CreateInstance which is heavily optimized. return(info.PropertyType.GetInstance()); } } } return(value); }