public static T ToObject <T>(this IDictionary <string, object> source, ITypeCache typeCache, bool dynamicObject = false) where T : class { if (typeCache == null) { throw new ArgumentNullException(nameof(typeCache)); } if (source == null) { return(default(T)); } if (typeCache.IsTypeAssignableFrom(typeof(IDictionary <string, object>), typeof(T))) { return(source as T); } if (typeof(T) == typeof(ODataEntry)) { return(CreateODataEntry(source, typeCache, dynamicObject) as T); } if (typeof(T) == typeof(string) || typeCache.IsValue(typeof(T))) { throw new InvalidOperationException($"Unable to convert structural data to {typeof(T).Name}."); } return((T)ToObject(source, typeCache, typeof(T), dynamicObject)); }
private static bool IsCollectionType(Type type, ITypeCache typeCache, object itemValue) { return ((type.IsArray || typeCache.IsGeneric(type) && typeCache.IsTypeAssignableFrom(typeof(System.Collections.IEnumerable), type)) && (itemValue as System.Collections.IEnumerable) != null); }
public static bool TryConvert(this ITypeCache typeCache, object value, Type targetType, out object result) { try { if (value == null) { result = typeCache.IsValue(targetType) ? Activator.CreateInstance(targetType) : null; } else if (typeCache.IsTypeAssignableFrom(targetType, value.GetType())) { result = value; } else if (targetType == typeof(string)) { result = value.ToString(); } else if (typeCache.IsEnumType(targetType) && value is string) { result = Enum.Parse(targetType, value.ToString(), true); } else if (targetType == typeof(byte[]) && value is string) { result = System.Convert.FromBase64String(value.ToString()); } else if (targetType == typeof(string) && value is byte[] bytes) { result = System.Convert.ToBase64String(bytes); } else if ((targetType == typeof(DateTime) || targetType == typeof(DateTime?)) && value is DateTimeOffset offset) { result = offset.DateTime; } else if ((targetType == typeof(DateTimeOffset) || targetType == typeof(DateTimeOffset?)) && value is DateTime time) { result = new DateTimeOffset(time); } else if (typeCache.IsEnumType(targetType)) { result = Enum.ToObject(targetType, value); } else if (targetType == typeof(Guid) && value is string) { result = new Guid(value.ToString()); } else if (Nullable.GetUnderlyingType(targetType) != null) { result = typeCache.Convert(value, Nullable.GetUnderlyingType(targetType)); } else { result = System.Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture); } return(true); } catch (Exception) { result = null; return(false); } }
private static IDictionary <string, object> CreateDynamicPropertiesContainer(Type type, ITypeCache typeCache, object instance, string dynamicPropertiesContainerName) { var property = typeCache.GetNamedProperty(type, dynamicPropertiesContainerName); if (property == null) { throw new ArgumentException($"Type {type} does not have property {dynamicPropertiesContainerName} "); } if (!typeCache.IsTypeAssignableFrom(typeof(IDictionary <string, object>), property.PropertyType)) { throw new InvalidOperationException($"Property {dynamicPropertiesContainerName} must implement IDictionary<string,object> interface"); } var dynamicProperties = new Dictionary <string, object>(); property.SetValue(instance, dynamicProperties, null); return(dynamicProperties); }
private static object ConvertCollection(Type type, ITypeCache typeCache, object itemValue) { var elementType = type.IsArray ? type.GetElementType() : typeCache.IsGeneric(type) && typeCache.GetGenericTypeArguments(type).Length == 1 ? typeCache.GetGenericTypeArguments(type)[0] : null; if (elementType == null) { return(null); } var count = GetCollectionCount(itemValue); var arrayValue = Array.CreateInstance(elementType, count); count = 0; foreach (var item in (itemValue as System.Collections.IEnumerable)) { arrayValue.SetValue(ConvertSingle(elementType, typeCache, item), count++); } if (type.IsArray || typeCache.IsTypeAssignableFrom(type, arrayValue.GetType())) { return(arrayValue); } else { var collectionTypes = new [] { typeof(IList <>).MakeGenericType(elementType), typeof(IEnumerable <>).MakeGenericType(elementType) }; var collectionType = type.GetConstructor(new [] { collectionTypes[0] }) != null ? collectionTypes[0] : collectionTypes[1]; var activator = _collectionActivators.GetOrAdd(new Tuple <Type, Type>(type, collectionType), t => type.CreateActivator(collectionType)); return(activator?.Invoke(arrayValue)); } }
public static object ToObject(this IDictionary <string, object> source, ITypeCache typeCache, Type type, bool dynamicObject = false) { if (typeCache == null) { throw new ArgumentNullException(nameof(typeCache)); } if (source == null) { return(null); } if (typeCache.IsTypeAssignableFrom(typeof(IDictionary <string, object>), type)) { return(source); } if (type == typeof(ODataEntry)) { return(CreateODataEntry(source, typeCache, dynamicObject)); } // Check before custom converter so we use the most appropriate type. if (source.ContainsKey(FluentCommand.AnnotationsLiteral)) { type = GetTypeFromAnnotation(source, typeCache, type); } if (typeCache.Converter.HasDictionaryConverter(type)) { return(typeCache.Converter.Convert(source, type)); } if (type.HasCustomAttribute(typeof(CompilerGeneratedAttribute), false)) { return(CreateInstanceOfAnonymousType(source, type, typeCache)); } var instance = CreateInstance(type); IDictionary <string, object> dynamicProperties = null; var dynamicPropertiesContainerName = typeCache.DynamicContainerName(type); if (!string.IsNullOrEmpty(dynamicPropertiesContainerName)) { dynamicProperties = CreateDynamicPropertiesContainer(type, typeCache, instance, dynamicPropertiesContainerName); } foreach (var item in source) { var property = FindMatchingProperty(type, typeCache, item); if (property != null && property.CanWrite) { if (item.Value != null) { property.SetValue(instance, ConvertValue(property.PropertyType, typeCache, item.Value), null); } } else { dynamicProperties?.Add(item.Key, item.Value); } } return(instance); }
public static object ToObject(this IDictionary <string, object> source, ITypeCache typeCache, Type type, bool dynamicObject = false) { if (typeCache == null) { throw new ArgumentNullException(nameof(typeCache)); } if (source == null) { return(null); } if (typeCache.IsTypeAssignableFrom(typeof(IDictionary <string, object>), type)) { return(source); } if (type == typeof(ODataEntry)) { return(CreateODataEntry(source, typeCache, dynamicObject)); } // Check before custom converter so we use the most appropriate type. if (source.ContainsKey(FluentCommand.AnnotationsLiteral)) { var annotations = source[FluentCommand.AnnotationsLiteral] as ODataEntryAnnotations; var odataType = annotations?.TypeName; if (!string.IsNullOrEmpty(odataType)) { // TODO: We could cast the ITypeCatcher to TypeCache and use it's property but it's a bit naughty - conditional? var resolver = ODataNameMatchResolver.NotStrict; if (!resolver.IsMatch(odataType, type.Name)) { // Ok, something other than the base type, see if we can match it var derived = typeCache.GetDerivedTypes(type).FirstOrDefault(x => resolver.IsMatch(odataType, typeCache.GetMappedName(x))); if (derived != null) { // Use the derived type from now on type = derived; } else { // TODO: Should we throw an exception here or log a warning here as we don't understand the data } } } } if (typeCache.Converter.HasDictionaryConverter(type)) { return(typeCache.Converter.Convert(source, type)); } var instance = CreateInstance(type); IDictionary <string, object> dynamicProperties = null; var dynamicPropertiesContainerName = typeCache.DynamicContainerName(type); if (!string.IsNullOrEmpty(dynamicPropertiesContainerName)) { dynamicProperties = CreateDynamicPropertiesContainer(type, typeCache, instance, dynamicPropertiesContainerName); } foreach (var item in source) { var property = FindMatchingProperty(type, typeCache, item); if (property != null && property.CanWrite) { if (item.Value != null) { property.SetValue(instance, ConvertValue(property.PropertyType, typeCache, item.Value), null); } } else { dynamicProperties?.Add(item.Key, item.Value); } } return(instance); }