private object GetPropertyValue(IEdmTypeReference propertyType, object value, ODataResource root)
        {
            if (value == null)
            {
                return(value);
            }

            switch (propertyType.TypeKind())
            {
            case EdmTypeKind.Complex:
                if (CustomConverters.HasObjectConverter(value.GetType()))
                {
                    return(CustomConverters.Convert(value, value.GetType()));
                }
                return(CreateODataEntry(propertyType.FullName(), value.ToDictionary(), root));

            case EdmTypeKind.Collection:
                var collection = propertyType.AsCollection();
                return(new ODataCollectionValue()
                {
                    TypeName = propertyType.FullName(),
                    Items = ((IEnumerable)value).Cast <object>().Select(x => GetPropertyValue(collection.ElementType(), x, root)),
                });

            case EdmTypeKind.Primitive:
                var mappedTypes = _typeMap.Where(x => x.Value == (propertyType.Definition as IEdmPrimitiveType).PrimitiveKind);
                if (mappedTypes.Any())
                {
                    foreach (var mappedType in mappedTypes)
                    {
                        if (Utils.TryConvert(value, mappedType.Key, out var result))
                        {
                            return(result);
                        }
                    }
                    throw new NotSupportedException($"Conversion is not supported from type {value.GetType()} to OData type {propertyType}");
                }
                return(value);

            case EdmTypeKind.Enum:
                return(new ODataEnumValue(value.ToString()));

            case EdmTypeKind.Untyped:
                return(new ODataUntypedValue {
                    RawValue = value.ToString()
                });

            case EdmTypeKind.None:
                if (CustomConverters.HasObjectConverter(value.GetType()))
                {
                    return(CustomConverters.Convert(value, value.GetType()));
                }
                throw new NotSupportedException($"Conversion is not supported from type {value.GetType()} to OData type {propertyType}");

            default:
                return(value);
            }
        }
Exemple #2
0
        private static object ToObject(this IDictionary <string, object> source, ITypeCache typeCache, Type type, string dynamicPropertiesContainerName, bool dynamicObject)
        {
            if (typeCache == null)
            {
                throw new ArgumentNullException(nameof(typeCache));
            }

            if (source == null)
            {
                return(null);
            }

            if (typeof(IDictionary <string, object>).IsTypeAssignableFrom(type))
            {
                return(source);
            }

            if (type == typeof(ODataEntry))
            {
                return(CreateODataEntry(source, typeCache, dynamicObject));
            }

            // TODO: Should be a method on TypeCache
            if (CustomConverters.HasDictionaryConverter(type))
            {
                return(CustomConverters.Convert(source, type));
            }

            var instance = CreateInstance(type);

            IDictionary <string, object> dynamicProperties = null;

            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);
        }
        private static object ToObject(this IDictionary <string, object> source, Type type, Func <object> instanceFactory,
                                       string dynamicPropertiesContainerName, bool dynamicObject)
        {
            if (source == null)
            {
                return(null);
            }
            if (typeof(IDictionary <string, object>).IsTypeAssignableFrom(type))
            {
                return(source);
            }
            if (type == typeof(ODataEntry))
            {
                return(CreateODataEntry(source, dynamicObject));
            }

            if (CustomConverters.HasDictionaryConverter(type))
            {
                return(CustomConverters.Convert(source, type));
            }

            var instance = instanceFactory();

            IDictionary <string, object> dynamicProperties = null;

            if (!string.IsNullOrEmpty(dynamicPropertiesContainerName))
            {
                dynamicProperties = CreateDynamicPropertiesContainer(type, instance, dynamicPropertiesContainerName);
            }

            foreach (var item in source)
            {
                var property = FindMatchingProperty(type, item);

                if (property != null && property.CanWrite && !property.IsNotMapped())
                {
                    if (item.Value != null)
                    {
                        property.SetValue(instance, ConvertValue(property.PropertyType, item.Value), null);
                    }
                }
                else if (dynamicProperties != null)
                {
                    dynamicProperties.Add(item.Key, item.Value);
                }
            }

            return(instance);
        }
        private object GetPropertyValue(IEdmTypeReference propertyType, object value)
        {
            if (value == null)
            {
                return(value);
            }

            switch (propertyType.TypeKind())
            {
            case EdmTypeKind.Complex:
                if (CustomConverters.HasObjectConverter(value.GetType()))
                {
                    return(CustomConverters.Convert(value, value.GetType()));
                }
                var complexTypeProperties = propertyType.AsComplex().StructuralProperties();
                return(new ODataComplexValue
                {
                    TypeName = propertyType.FullName(),
                    Properties = value.ToDictionary()
                                 .Where(val => complexTypeProperties.Any(p => p.Name == val.Key))
                                 .Select(x => new ODataProperty
                    {
                        Name = x.Key,
                        Value = GetPropertyValue(complexTypeProperties, x.Key, x.Value),
                    })
                });

            case EdmTypeKind.Collection:
                var collection = propertyType.AsCollection();
                return(new ODataCollectionValue()
                {
                    TypeName = propertyType.FullName(),
                    Items = ((IEnumerable)value).Cast <object>().Select(x => GetPropertyValue(collection.ElementType(), x)),
                });

            case EdmTypeKind.Primitive:
                var mappedTypes = _typeMap.Where(x => x.Value == (propertyType.Definition as IEdmPrimitiveType).PrimitiveKind);
                if (mappedTypes.Any())
                {
                    foreach (var mappedType in mappedTypes)
                    {
                        object result;
                        if (Utils.TryConvert(value, mappedType.Key, out result))
                        {
                            return(result);
                        }
                    }
                    throw new NotSupportedException(string.Format("Conversion is not supported from type {0} to OData type {1}", value.GetType(), propertyType));
                }
                return(value);

            case EdmTypeKind.Enum:
                return(value.ToString());

            case EdmTypeKind.None:
                if (CustomConverters.HasObjectConverter(value.GetType()))
                {
                    return(CustomConverters.Convert(value, value.GetType()));
                }
                throw new NotSupportedException(string.Format("Conversion is not supported from type {0} to OData type {1}", value.GetType(), propertyType));

            default:
                return(value);
            }
        }
Exemple #5
0
        private static object ToObject(this IDictionary <string, object> source, Type type, Func <object> instanceFactory, bool dynamicObject)
        {
            if (source == null)
            {
                return(null);
            }
            if (typeof(IDictionary <string, object>).IsTypeAssignableFrom(type))
            {
                return(source);
            }
            if (type == typeof(ODataEntry))
            {
                return(CreateODataEntry(source, dynamicObject));
            }

            if (CustomConverters.HasConverter(type))
            {
                return(CustomConverters.Convert(source, type));
            }

            var instance = instanceFactory();

            Func <Type, bool> IsCompoundType = fieldOrPropertyType =>
                                               !fieldOrPropertyType.IsValue() && !fieldOrPropertyType.IsArray && fieldOrPropertyType != typeof(string);

            Func <Type, object, bool> IsCollectionType = (fieldOrPropertyType, itemValue) =>
                                                         (fieldOrPropertyType.IsArray ||
                                                          fieldOrPropertyType.IsGeneric() &&
                                                          typeof(System.Collections.IEnumerable).IsTypeAssignableFrom(fieldOrPropertyType)) &&
                                                         (itemValue as System.Collections.IEnumerable) != null;

            Func <Type, object, object> ConvertEnum = (fieldOrPropertyType, itemValue) =>
            {
                if (itemValue == null)
                {
                    return(null);
                }
                var stringValue = itemValue.ToString();
                int intValue;
                if (int.TryParse(stringValue, out intValue))
                {
                    object result;
                    Utils.TryConvert(intValue, fieldOrPropertyType, out result);
                    return(result);
                }
                else
                {
                    return(Enum.Parse(fieldOrPropertyType, stringValue, false));
                }
            };

            Func <Type, object, object> ConvertSingle = (fieldOrPropertyType, itemValue) =>
                                                        IsCompoundType(fieldOrPropertyType)
                ? itemValue.ToDictionary().ToObject(fieldOrPropertyType)
                : fieldOrPropertyType.IsEnumType()
                    ? ConvertEnum(fieldOrPropertyType, itemValue)
                    : itemValue;

            Func <Type, object, object> ConvertCollection = (fieldOrPropertyType, itemValue) =>
            {
                var elementType = fieldOrPropertyType.IsArray
                    ? fieldOrPropertyType.GetElementType()
                    : fieldOrPropertyType.IsGeneric() && fieldOrPropertyType.GetGenericTypeArguments().Length == 1
                        ? fieldOrPropertyType.GetGenericTypeArguments()[0]
                        : null;
                if (elementType == null)
                {
                    return(null);
                }

                var count      = (itemValue as System.Collections.IEnumerable).Cast <object>().Count();
                var arrayValue = Array.CreateInstance(elementType, count);

                count = 0;
                foreach (var item in (itemValue as System.Collections.IEnumerable))
                {
                    (arrayValue as Array).SetValue(ConvertSingle(elementType, item), count++);
                }

                if (fieldOrPropertyType.IsArray || fieldOrPropertyType.IsTypeAssignableFrom(arrayValue.GetType()))
                {
                    return(arrayValue);
                }
                else
                {
                    var typedef        = typeof(IEnumerable <>);
                    var enumerableType = typedef.MakeGenericType(elementType);
                    var ctor           = fieldOrPropertyType.GetDeclaredConstructors().FirstOrDefault(
                        x => x.GetParameters().Length == 1 && x.GetParameters().First().ParameterType == enumerableType);
                    return(ctor != null
                        ? ctor.Invoke(new object[] { arrayValue })
                        : null);
                }
            };

            Func <Type, object, object> ConvertValue = (fieldOrPropertyType, itemValue) =>
                                                       IsCollectionType(fieldOrPropertyType, itemValue)
                ? ConvertCollection(fieldOrPropertyType, itemValue)
                : ConvertSingle(fieldOrPropertyType, itemValue);

            foreach (var item in source)
            {
                if (item.Value != null)
                {
                    var property = type.GetAnyProperty(item.Key) ??
                                   type.GetAllProperties().FirstOrDefault(x => x.GetMappedName() == item.Key);

                    if (property != null && property.CanWrite && !property.IsNotMapped())
                    {
                        property.SetValue(instance, ConvertValue(property.PropertyType, item.Value), null);
                    }
                }
            }

            return(instance);
        }