Esempio n. 1
0
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }
            if (edmType == null)
            {
                throw Error.ArgumentNull("edmType");
            }

            if (!edmType.IsCollection())
            {
                throw new SerializationException(
                          Error.Format(SRResources.TypeCannotBeDeserialized, edmType.ToTraceString(), typeof(ODataMediaTypeFormatter)));
            }

            IEdmCollectionTypeReference collectionType = edmType.AsCollection();
            IEdmTypeReference           elementType    = collectionType.ElementType();

            ODataCollectionValue collection = item as ODataCollectionValue;

            if (collection == null)
            {
                throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataCollectionValue).Name);
            }
            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            IEnumerable result = ReadCollectionValue(collection, elementType, readContext);

            if (result != null)
            {
                if (readContext.IsUntyped && elementType.IsComplex())
                {
                    EdmComplexObjectCollection complexCollection = new EdmComplexObjectCollection(collectionType);
                    foreach (EdmComplexObject complexObject in result)
                    {
                        complexCollection.Add(complexObject);
                    }
                    return(complexCollection);
                }
                else if (readContext.IsUntyped && elementType.IsEnum())
                {
                    EdmEnumObjectCollection enumCollection = new EdmEnumObjectCollection(collectionType);
                    foreach (EdmEnumObject enumObject in result)
                    {
                        enumCollection.Add(enumObject);
                    }
                    return(enumCollection);
                }
                else
                {
                    Type        elementClrType = EdmLibHelpers.GetClrType(elementType, readContext.Model);
                    IEnumerable castedResult   = _castMethodInfo.MakeGenericMethod(elementClrType).Invoke(null, new object[] { result }) as IEnumerable;
                    return(castedResult);
                }
            }
            return(null);
        }
Esempio n. 2
0
        private static object InterceptValue(object graph, IEdmTypeReference expectedType, string elementName,
                                             ODataSerializerContext writeContext, object declaringInstance, IEdmTypeReference declaringTypeReference,
                                             IEdmType declaringType, Type declaringClrType)
        {
            var modelBuilder  = EdmModelHelperMethods.Configuration[writeContext.Model];
            var assemblyNames = writeContext.Request.HttpContext.RequestServices.GetService <AssembliesResolver>();
            var clrType       = EdmLibHelpers.GetClrType(expectedType, writeContext.Model, assemblyNames);
            var serializers   = modelBuilder.GetSerializeInterceptors(
                clrType).ToList();
            var isRoot = declaringInstance == null &&
                         declaringTypeReference == null &&
                         declaringType == null &&
                         declaringClrType == null;

            if (serializers.Any())
            {
                if (declaringClrType == null && declaringTypeReference != null)
                {
                    declaringClrType = declaringType != null
                                                ? EdmLibHelpers.GetClrType(declaringType, writeContext.Model, assemblyNames)
                                                : EdmLibHelpers.GetClrType(declaringTypeReference, writeContext.Model, assemblyNames);
                }
                var vp = new ValueInterceptor(
                    graph, clrType, elementName, declaringInstance, declaringClrType, isRoot);
                foreach (var serializer in serializers)
                {
                    if (!serializer.Process(vp))
                    {
                        break;
                    }
                }
                graph = vp.Value;
            }
            return(graph);
        }
        private static HttpActionDescriptor MapForRestierIfNecessary(HttpRequestMessage request, HttpActionDescriptor actionDescriptor)
        {
            Contract.Requires(request != null);
            Contract.Requires(actionDescriptor != null);
            Contract.Requires(actionDescriptor.ControllerDescriptor != null);

            if (actionDescriptor.ControllerDescriptor.ControllerName == "Restier")
            {
                var  odataPath     = request.ODataProperties().Path;
                var  entitySetName = odataPath.NavigationSource.Name;
                Type returnType    = null;
                if (ReturnsValue(request))
                {
                    var model = request.GetRequestContainer().GetRequiredService <IEdmModel>();
                    if (odataPath.EdmType.TypeKind == EdmTypeKind.Collection)
                    {
                        var edmElementType = ((IEdmCollectionType)odataPath.EdmType).ElementType;
                        var elementType    = EdmLibHelpers.GetClrType(edmElementType, model);
                        var queryableType  = typeof(IQueryable <>);
                        returnType = queryableType.MakeGenericType(elementType);
                    }
                    else
                    {
                        returnType = EdmLibHelpers.GetClrType(odataPath.EdmType.ToEdmTypeReference(false), model);
                    }
                }

                return(new RestierHttpActionDescriptor(actionDescriptor.ActionName, returnType, actionDescriptor.SupportedHttpMethods, entitySetName)
                {
                    Configuration = actionDescriptor.Configuration,
                    ControllerDescriptor = actionDescriptor.ControllerDescriptor
                });
            }
            return(actionDescriptor);
        }
Esempio n. 4
0
        private Expression BindFilterQueryNode(FilterQueryNode filterNode)
        {
            Type filterType = EdmLibHelpers.GetClrType(filterNode.ItemType, _model, _assembliesResolver);
            ParameterExpression filterParameter = Expression.Parameter(filterType, filterNode.Parameter.Name);

            _lambdaParameters = new Dictionary <string, ParameterExpression>();
            _lambdaParameters.Add(filterNode.Parameter.Name, filterParameter);

            Expression body = Bind(filterNode.Expression);

            body = ApplyNullPropagationForFilterBody(body);

            Expression filterExpression = Expression.Lambda(body, filterParameter);

            if (_parametersStack.Count != 0)
            {
                _lambdaParameters = _parametersStack.Pop();
            }
            else
            {
                _lambdaParameters = null;
            }

            return(filterExpression);
        }
        internal static Type GetClrTypeForUntypedDelta(IEdmTypeReference edmType)
        {
            Contract.Assert(edmType != null);

            switch (edmType.TypeKind())
            {
            case EdmTypeKind.Primitive:
                return(EdmLibHelpers.GetClrType(edmType.AsPrimitive(), EdmCoreModel.Instance));

            case EdmTypeKind.Complex:
                return(typeof(EdmComplexObject));

            case EdmTypeKind.Entity:
                return(typeof(EdmEntityObject));

            case EdmTypeKind.Collection:
                IEdmTypeReference elementType = edmType.AsCollection().ElementType();
                if (elementType.IsPrimitive())
                {
                    Type elementClrType = GetClrTypeForUntypedDelta(elementType);
                    return(typeof(List <>).MakeGenericType(elementClrType));
                }
                else if (elementType.IsComplex())
                {
                    return(typeof(EdmComplexObjectCollection));
                }
                else if (elementType.IsEntity())
                {
                    return(typeof(EdmEntityObjectCollection));
                }
                break;
            }

            throw Error.InvalidOperation(SRResources.UnsupportedEdmType, edmType.ToTraceString(), edmType.TypeKind());
        }
Esempio n. 6
0
        private Expression BindConvertQueryNode(ConvertQueryNode convertQueryNode)
        {
            Contract.Assert(convertQueryNode != null);
            Contract.Assert(convertQueryNode.TypeReference != null);

            Expression source = Bind(convertQueryNode.Source);

            Type conversionType = EdmLibHelpers.GetClrType(convertQueryNode.TypeReference, _model, _assembliesResolver);

            if (conversionType == typeof(bool?) && source.Type == typeof(bool))
            {
                // we handle null propagation ourselves. So, if converting from bool to Nullable<bool> ignore.
                return(source);
            }
            else if (source == _nullConstant)
            {
                return(source);
            }
            else
            {
                Type sourceUnderlyingType = Nullable.GetUnderlyingType(source.Type) ?? source.Type;
                if (sourceUnderlyingType.IsEnum)
                {
                    // we handle enum conversions ourselves
                    return(source);
                }
                else
                {
                    return(Expression.Convert(source, conversionType));
                }
            }
        }
Esempio n. 7
0
        public override object ReadInline(ODataFeed feed, ODataDeserializerContext readContext)
        {
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }

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

            ODataEntryDeserializer deserializer = DeserializerProvider.GetODataDeserializer(_edmEntityType);
            IList feedValue = CreateNewCollection(EdmLibHelpers.GetClrType(_edmEntityType, EdmModel));

            ODataFeedAnnotation feedAnnotation = feed.GetAnnotation <ODataFeedAnnotation>();

            Contract.Assert(feedAnnotation != null, "Each feed we create should gave annotation on it.");

            foreach (ODataEntry entry in feedAnnotation)
            {
                ODataEntryAnnotation annotation = entry.GetAnnotation <ODataEntryAnnotation>();
                Contract.Assert(annotation != null);

                feedValue.Add(deserializer.ReadInline(entry, readContext));
            }

            return(feedValue);
        }
Esempio n. 8
0
        private Expression BindSingleResourceCastFunctionCall(SingleResourceFunctionCallNode node)
        {
            Contract.Assert(ClrCanonicalFunctions.CastFunctionName == node.Name);

            Expression[] arguments = BindArguments(node.Parameters);

            Contract.Assert(arguments.Length == 2);

            string   targetEdmTypeName = (string)((ConstantNode)node.Parameters.Last()).Value;
            IEdmType targetEdmType     = Model.FindType(targetEdmTypeName);
            Type     targetClrType     = null;

            if (targetEdmType != null)
            {
                targetClrType = EdmLibHelpers.GetClrType(targetEdmType.ToEdmTypeReference(false), Model);
            }

            if (arguments[0].Type == targetClrType)
            {
                // We only support to cast Entity type to the same type now.
                return(arguments[0]);
            }
            else if (arguments[0].Type.IsAssignableFrom(targetClrType))
            {
                // To support to cast Entity/Complex type to the sub type now.
                Expression source = BindCastSourceNode(node.Source);

                return(Expression.TypeAs(source, targetClrType));
            }
            else
            {
                // Cast fails and return null.
                return(NullConstant);
            }
        }
Esempio n. 9
0
        private static object ConvertDynamicEnumValue(object value, ODataDeserializerContext readContext)
        {
            Contract.Assert(value != null);
            Contract.Assert(readContext != null);
            Contract.Assert(readContext.Model != null);

            ODataEnumValue enumValue = value as ODataEnumValue;

            Contract.Assert(enumValue != null);

            IEdmType edmType = readContext.Model.FindType(enumValue.TypeName);

            Contract.Assert(edmType != null);

            if (!readContext.IsUntyped)
            {
                Type enumType = EdmLibHelpers.GetClrType(edmType, readContext.Model);
                return(Enum.Parse(enumType, enumValue.Value));
            }
            else
            {
                // TODO: https://aspnetwebstack.codeplex.com/workitem/1956:
                // Enum (de)serialization on un-type doesn't work
                // Currently, just return the "string" value of the ODataEnumValue for untype enum type.
                return(enumValue.Value);
            }
        }
Esempio n. 10
0
        internal Expression CreatePropertyNameExpression(IEdmEntityType elementType, IEdmProperty property, Expression source)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType;

            Contract.Assert(declaringType != null, "only entity types are projected.");

            // derived navigation property using cast
            if (elementType != declaringType)
            {
                Type originalType = EdmLibHelpers.GetClrType(elementType, _model);
                Type castType     = EdmLibHelpers.GetClrType(declaringType, _model);
                if (castType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType, declaringType.FullName()));
                }

                if (!castType.IsAssignableFrom(originalType))
                {
                    // Expression
                    //          source is navigationPropertyDeclaringType ? propertyName : null
                    return(Expression.Condition(
                               test: Expression.TypeIs(source, castType),
                               ifTrue: Expression.Constant(property.Name),
                               ifFalse: Expression.Constant(null, typeof(string))));
                }
            }

            // Expression
            //          "propertyName"
            return(Expression.Constant(property.Name));
        }
Esempio n. 11
0
        // OData formatter requires the type name of the entity that is being written if the type has derived types.
        // Expression
        //      source is GrandChild ? "GrandChild" : ( source is Child ? "Child" : "Root" )
        // Notice that the order is important here. The most derived type must be the first to check.
        // If entity framework had a way to figure out the type name without selecting the whole object, we don't have to do this magic.
        internal static Expression CreateTypeNameExpression(Expression source, IEdmEntityType elementType, IEdmModel model)
        {
            IReadOnlyList <IEdmEntityType> derivedTypes = GetAllDerivedTypes(elementType, model);

            if (derivedTypes.Count == 0)
            {
                // no inheritance.
                return(null);
            }
            else
            {
                Expression expression = Expression.Constant(elementType.FullName());
                for (int i = 0; i < derivedTypes.Count; i++)
                {
                    Type clrType = EdmLibHelpers.GetClrType(derivedTypes[i], model);
                    if (clrType == null)
                    {
                        throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType, derivedTypes[0].FullName()));
                    }

                    expression = Expression.Condition(
                        test: Expression.TypeIs(source, clrType),
                        ifTrue: Expression.Constant(derivedTypes[i].FullName()),
                        ifFalse: expression);
                }

                return(expression);
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Creates a new instance of the backing CLR object for <see cref="ODataEntityDeserializer.EntityType"/>.
        /// </summary>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The created CLR object.</returns>
        public virtual object CreateEntityResource(ODataDeserializerContext readContext)
        {
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }

            IEdmModel model = readContext.Model;

            if (model == null)
            {
                throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
            }

            Type clrType = EdmLibHelpers.GetClrType(EntityType, model);

            if (clrType == null)
            {
                throw new ODataException(
                          Error.Format(SRResources.MappingDoesNotContainEntityType, EntityType.FullName()));
            }

            object resource;

            if (!readContext.IsPatchMode)
            {
                resource = Activator.CreateInstance(clrType);
            }
            else
            {
                resource = Activator.CreateInstance(readContext.PatchEntityType, clrType);
            }

            return(resource);
        }
        private static void ProcessResourceSet(object feed, IEdmCollectionTypeReference resourceSetType, ODataDeserializerContext readContext, ODataDeserializerProvider deserializerProvider, Dictionary <string, object> payload, string parameterName)
        {
            ODataResourceSetDeserializer resourceSetDeserializer = (ODataResourceSetDeserializer)deserializerProvider.GetEdmTypeDeserializer(resourceSetType);

            object result = resourceSetDeserializer.ReadInline(feed, resourceSetType, readContext);

            IEdmTypeReference elementTypeReference = resourceSetType.ElementType();

            Contract.Assert(elementTypeReference.IsStructured());

            IEnumerable enumerable = result as IEnumerable;

            if (enumerable != null)
            {
                if (readContext.IsUntyped)
                {
                    payload[parameterName] = enumerable.ConvertToEdmObject(resourceSetType);
                }
                else
                {
                    Type        elementClrType = EdmLibHelpers.GetClrType(elementTypeReference, readContext.Model);
                    IEnumerable castedResult   =
                        _castMethodInfo.MakeGenericMethod(elementClrType)
                        .Invoke(null, new[] { result }) as IEnumerable;
                    payload[parameterName] = castedResult;
                }
            }
        }
Esempio n. 14
0
        internal Expression CreateConvertExpression(ConvertNode convertNode, Expression source)
        {
            Type conversionType = EdmLibHelpers.GetClrType(convertNode.TypeReference, Model, InternalAssembliesResolver);

            if (conversionType == typeof(bool?) && source.Type == typeof(bool))
            {
                // we handle null propagation ourselves. So, if converting from bool to Nullable<bool> ignore.
                return(source);
            }
            else if (conversionType == typeof(Date?) &&
                     (source.Type == typeof(DateTimeOffset?) || source.Type == typeof(DateTime?)))
            {
                return(source);
            }
            if ((conversionType == typeof(TimeOfDay?) && source.Type == typeof(TimeOfDay)) ||
                ((conversionType == typeof(Date?) && source.Type == typeof(Date))))
            {
                return(source);
            }
            else if (conversionType == typeof(TimeOfDay?) &&
                     (source.Type == typeof(DateTimeOffset?) || source.Type == typeof(DateTime?) || source.Type == typeof(TimeSpan?)))
            {
                return(source);
            }
            else if (IsDateAndTimeRelated(conversionType) && IsDateAndTimeRelated(source.Type))
            {
                return(source);
            }
            else if (source == NullConstant)
            {
                return(source);
            }
            else
            {
                if (TypeHelper.IsEnum(source.Type))
                {
                    // we handle enum conversions ourselves
                    return(source);
                }
                else
                {
                    // if a cast is from Nullable<T> to Non-Nullable<T> we need to check if source is null
                    if (QuerySettings.HandleNullPropagation == HandleNullPropagationOption.True &&
                        IsNullable(source.Type) && !IsNullable(conversionType))
                    {
                        // source == null ? null : source.Value
                        return
                            (Expression.Condition(
                                 test: CheckForNull(source),
                                 ifTrue: Expression.Constant(null, ToNullable(conversionType)),
                                 ifFalse: Expression.Convert(ExtractValueFromNullableExpression(source), ToNullable(conversionType))));
                    }
                    else
                    {
                        return(Expression.Convert(source, conversionType));
                    }
                }
            }
        }
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            if (edmType == null)
            {
                throw Error.ArgumentNull("edmType");
            }

            if (!edmType.IsCollection() || !edmType.AsCollection().ElementType().IsStructured())
            {
                throw Error.Argument("edmType", SRResources.TypeMustBeResourceSet, edmType.ToTraceString());
            }

            ODataResourceSetWrapper resourceSet = item as ODataResourceSetWrapper;

            if (resourceSet == null)
            {
                throw Error.Argument("item", SRResources.ArgumentMustBeOfType, typeof(ODataResourceSetWrapper).Name);
            }

            // Recursion guard to avoid stack overflows
            RuntimeHelpers.EnsureSufficientExecutionStack();

            IEdmStructuredTypeReference elementType = edmType.AsCollection().ElementType().AsStructured();

            IEnumerable result = ReadResourceSet(resourceSet, elementType, readContext);

            if (result != null && elementType.IsComplex())
            {
                if (readContext.IsUntyped)
                {
                    EdmComplexObjectCollection complexCollection = new EdmComplexObjectCollection(edmType.AsCollection());
                    foreach (EdmComplexObject complexObject in result)
                    {
                        complexCollection.Add(complexObject);
                    }
                    return(complexCollection);
                }
                else
                {
                    Type        elementClrType = EdmLibHelpers.GetClrType(elementType, readContext.Model);
                    IEnumerable castedResult   =
                        CastMethodInfo.MakeGenericMethod(elementClrType).Invoke(null, new object[] { result }) as
                        IEnumerable;
                    return(castedResult);
                }
            }
            else
            {
                return(result);
            }
        }
Esempio n. 16
0
        /// <summary>
        /// Creates a new instance of the backing CLR object for the given entity type.
        /// </summary>
        /// <param name="entityType">The EDM type of the entity to create.</param>
        /// <param name="readContext">The deserializer context.</param>
        /// <returns>The created CLR object.</returns>
        public virtual object CreateEntityResource(IEdmEntityTypeReference entityType, ODataDeserializerContext readContext)
        {
            if (readContext == null)
            {
                throw Error.ArgumentNull("readContext");
            }
            if (entityType == null)
            {
                throw Error.ArgumentNull("entityType");
            }

            IEdmModel model = readContext.Model;

            if (model == null)
            {
                throw Error.Argument("readContext", SRResources.ModelMissingFromReadContext);
            }

            if (readContext.IsUntyped)
            {
                return(new EdmEntityObject(entityType));
            }
            else
            {
                Type clrType = EdmLibHelpers.GetClrType(entityType, model);
                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainEntityType, entityType.FullName()));
                }

                if (readContext.IsDeltaOfT)
                {
                    IEnumerable <string> structuralProperties = entityType.StructuralProperties()
                                                                .Select(edmProperty => EdmLibHelpers.GetClrPropertyName(edmProperty, model));

                    if (entityType.IsOpen())
                    {
                        PropertyInfo dynamicDictionaryPropertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(
                            entityType.StructuredDefinition(), model);

                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties,
                                                        dynamicDictionaryPropertyInfo));
                    }
                    else
                    {
                        return(Activator.CreateInstance(readContext.ResourceType, clrType, structuralProperties));
                    }
                }
                else
                {
                    return(Activator.CreateInstance(clrType));
                }
            }
        }
Esempio n. 17
0
        private Expression BindConstantQueryNode(ConstantQueryNode constantNode)
        {
            Contract.Assert(constantNode != null);

            if (constantNode.Value == null)
            {
                return(_nullConstant);
            }

            return(Expression.Constant(constantNode.Value, EdmLibHelpers.GetClrType(constantNode.TypeReference, _model, _assembliesResolver)));
        }
Esempio n. 18
0
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            Type clrType = EdmLibHelpers.GetClrType(edmType, readContext.Model);

            return(EnumDeserializationHelpers.ConvertEnumValue(item, clrType));
        }
Esempio n. 19
0
        internal static object CreateResource(IEdmComplexType edmComplexType, IEdmModel edmModel)
        {
            Type clrType = EdmLibHelpers.GetClrType(new EdmComplexTypeReference(edmComplexType, isNullable: true), edmModel);

            if (clrType == null)
            {
                throw Error.Argument("edmComplexType", SRResources.MappingDoesNotContainEntityType, edmComplexType.FullName());
            }

            return(Activator.CreateInstance(clrType));
        }
Esempio n. 20
0
        /// <summary>
        /// Creates new delta object for target resource.
        /// </summary>
        /// <param name="readContext">The deserializer context.</param>
        /// <param name="resourceWrapper">The resource object containing the annotations.</param>
        /// <param name="structuredType">The type of the resource.</param>
        /// <returns></returns>
        protected virtual Delta CreateDeltaInstance(ODataDeserializerContext readContext, ODataResourceWrapper resourceWrapper, IEdmStructuredTypeReference structuredType)
        {
            Type clrPropertyType = EdmLibHelpers.GetClrType(structuredType, readContext.Model);
            Type deltaType       = typeof(Delta <>).MakeGenericType(clrPropertyType);

            // set navigation properties as editable so that @odata.id works for nested resources
            IEnumerable <string> structuralProperties = GetUpdatableProperties(readContext.Model, structuredType);

            Delta propertyValueDelta = (Delta)Activator.CreateInstance(deltaType, clrPropertyType, structuralProperties);

            return(propertyValueDelta);
        }
Esempio n. 21
0
        /// <summary>
        /// Binds a <see cref="CollectionResourceCastNode"/> to create a LINQ <see cref="Expression"/> that
        /// represents the semantics of the <see cref="CollectionResourceCastNode"/>.
        /// </summary>
        /// <param name="node">The node to bind.</param>
        /// <returns>The LINQ <see cref="Expression"/> created.</returns>
        public virtual Expression BindCollectionResourceCastNode(CollectionResourceCastNode node)
        {
            IEdmStructuredTypeReference structured = node.ItemStructuredType;

            Contract.Assert(structured != null, "NS casts can contain only structured types");

            Type clrType = EdmLibHelpers.GetClrType(structured, Model);

            Expression source = BindCastSourceNode(node.Source);

            return(OfType(source, clrType));
        }
Esempio n. 22
0
        private object ReadNestedResourceInline(ODataResourceWrapper resourceWrapper, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            Contract.Assert(edmType != null);
            Contract.Assert(readContext != null);

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

            ODataEdmTypeDeserializer deserializer = DeserializerProvider.GetEdmTypeDeserializer(edmType);

            if (deserializer == null)
            {
                throw new SerializationException(Error.Format(SRResources.TypeCannotBeDeserialized,
                                                              edmType.FullName(), typeof(ODataMediaTypeFormatter)));
            }

            IEdmStructuredTypeReference structuredType = edmType.AsStructured();

            var nestedReadContext = new ODataDeserializerContext
            {
                Path  = readContext.Path,
                Model = readContext.Model,
            };

            if (readContext.IsUntyped)
            {
                if (structuredType.IsEntity())
                {
                    nestedReadContext.ResourceType = typeof(EdmEntityObject);
                }
                else
                {
                    nestedReadContext.ResourceType = typeof(EdmComplexObject);
                }
            }
            else
            {
                Type clrType = EdmLibHelpers.GetClrType(structuredType, readContext.Model);

                if (clrType == null)
                {
                    throw new ODataException(
                              Error.Format(SRResources.MappingDoesNotContainResourceType, structuredType.FullName()));
                }

                nestedReadContext.ResourceType = clrType;
            }

            return(deserializer.ReadInline(resourceWrapper, edmType, nestedReadContext));
        }
        private static bool ApplyDynamicProperty(ODataProperty property, IEdmStructuredType structuredType,
                                                 object resource, ODataDeserializerProvider deserializerProvider, ODataDeserializerContext readContext)
        {
            PropertyInfo propertyInfo = EdmLibHelpers.GetDynamicPropertyDictionary(structuredType,
                                                                                   readContext.Model);

            if (propertyInfo == null)
            {
                return(false);
            }

            IDictionary <string, object> dynamicPropertyDictionary = propertyInfo.GetValue(resource)
                                                                     as IDictionary <string, object>;

            if (dynamicPropertyDictionary == null)
            {
                dynamicPropertyDictionary = new Dictionary <string, object>();
                propertyInfo.SetValue(resource, dynamicPropertyDictionary);
            }

            if (dynamicPropertyDictionary.ContainsKey(property.Name))
            {
                throw Error.InvalidOperation(SRResources.DuplicateDynamicPropertyNameFound,
                                             property.Name, structuredType.FullTypeName());
            }

            EdmTypeKind       propertyKind;
            IEdmTypeReference propertyType = null;
            object            value        = ConvertValue(property.Value, ref propertyType, deserializerProvider, readContext, out propertyKind);

            if (propertyKind == EdmTypeKind.Collection)
            {
                throw Error.InvalidOperation(SRResources.CollectionNotAllowedAsDynamicProperty, property.Name);
            }

            if (propertyKind == EdmTypeKind.Enum)
            {
                ODataEnumValue enumValue = (ODataEnumValue)value;
                IEdmModel      model     = readContext.Model;
                IEdmType       edmType   = model.FindType(enumValue.TypeName);
                if (edmType == null)
                {
                    return(false);
                }

                Type enumType = EdmLibHelpers.GetClrType(edmType, model);
                value = Enum.Parse(enumType, enumValue.Value);
            }

            dynamicPropertyDictionary.Add(property.Name, value);
            return(true);
        }
Esempio n. 24
0
        private object BuildResourceInstance()
        {
            if (EdmObject == null)
            {
                return(null);
            }

            TypedEdmStructuredObject edmStructruredObject = EdmObject as TypedEdmStructuredObject;

            if (edmStructruredObject != null)
            {
                return(edmStructruredObject.Instance);
            }

            SelectExpandWrapper selectExpandWrapper = EdmObject as SelectExpandWrapper;

            if (selectExpandWrapper != null && selectExpandWrapper.UntypedInstance != null)
            {
                return(selectExpandWrapper.UntypedInstance);
            }

            Type clrType = EdmLibHelpers.GetClrType(StructuredType, EdmModel);

            if (clrType == null)
            {
                throw new InvalidOperationException(Error.Format(SRResources.MappingDoesNotContainResourceType, StructuredType.FullTypeName()));
            }

            object resource = Activator.CreateInstance(clrType);

            foreach (IEdmStructuralProperty property in StructuredType.StructuralProperties())
            {
                object value;
                if (EdmObject.TryGetPropertyValue(property.Name, out value) && value != null)
                {
                    string propertyName = EdmLibHelpers.GetClrPropertyName(property, EdmModel);

                    if (value.GetType().IsCollection())
                    {
                        DeserializationHelpers.SetCollectionProperty(resource, property, value, propertyName);
                    }
                    else
                    {
                        DeserializationHelpers.SetProperty(resource, propertyName, value);
                    }
                }
            }

            return(resource);
        }
        private void AddReferenceToCollection(object entityResource, IEdmNavigationProperty navigationProperty, object childEntityResource)
        {
            PropertyInfo clrProperty = entityResource.GetType().GetProperty(navigationProperty.Name);
            IList        list        = clrProperty.GetValue(entityResource, index: null) as IList;

            if (list == null)
            {
                Type elementType = EdmLibHelpers.GetClrType(new EdmEntityTypeReference(navigationProperty.ToEntityType(), isNullable: true), EdmModel);
                list = Activator.CreateInstance(typeof(Collection <>).MakeGenericType(elementType)) as IList;
                clrProperty.SetValue(entityResource, list, index: null);
            }

            list.Add(childEntityResource);
        }
Esempio n. 26
0
        internal static object CreateResource(IEdmComplexType edmComplexType, IEdmModel edmModel)
        {
            Contract.Assert(edmComplexType != null);
            Contract.Assert(edmModel != null);

            Type clrType = EdmLibHelpers.GetClrType(new EdmComplexTypeReference(edmComplexType, isNullable: true), edmModel);

            if (clrType == null)
            {
                throw Error.InvalidOperation(SRResources.MappingDoesNotContainEntityType, edmComplexType.FullName());
            }

            return(Activator.CreateInstance(clrType));
        }
        /// <summary>
        /// Generates type by provided definition.
        /// </summary>
        /// <param name="model"></param>
        /// <param name="assemblyProvider"></param>
        /// <param name="propertyNodes"></param>
        /// <param name="expressions"></param>
        /// <returns></returns>
        /// <remarks>
        /// We create new assembly each time, but they will be collected by GC.
        /// Current performance testing results is 0.5ms per type. We should consider caching types, however trade off is between CPU perfomance and memory usage (might be it will we an option for library user)
        /// </remarks>
        public static Type GetResultType <T>(
            IEdmModel model,
            IAssemblyProvider assemblyProvider,
            IEnumerable <GroupByPropertyNode> propertyNodes = null,
            IEnumerable <AggregateExpression> expressions   = null) where T : AggregationWrapper
        {
            Contract.Assert(model != null);

            // Do not have properties, just return base class
            if ((expressions == null || !expressions.Any()) && (propertyNodes == null || !propertyNodes.Any()))
            {
                return(typeof(T));
            }

            TypeBuilder tb = GetTypeBuilder <T>(DynamicTypeName);

            if (expressions != null && expressions.Any())
            {
                foreach (var field in expressions)
                {
                    if (field.TypeReference.Definition.TypeKind == EdmTypeKind.Primitive)
                    {
                        var primitiveType = EdmLibHelpers.GetClrType(field.TypeReference, model, assemblyProvider);
                        CreateProperty(tb, field.Alias, primitiveType);
                    }
                }
            }

            if (propertyNodes != null && propertyNodes.Any())
            {
                foreach (var field in propertyNodes)
                {
                    if (field.Expression != null && field.TypeReference.Definition.TypeKind == EdmTypeKind.Primitive)
                    {
                        var primitiveType = EdmLibHelpers.GetClrType(field.TypeReference, model, assemblyProvider);
                        CreateProperty(tb, field.Name, primitiveType);
                    }
                    else
                    {
                        var complexProp = GetResultType <AggregationWrapper>(model, assemblyProvider, field.ChildTransformations);
                        CreateProperty(tb, field.Name, complexProp);
                    }
                }
            }

            var typeInfo = tb.CreateTypeInfo();

            return(typeInfo.AsType());
        }
Esempio n. 28
0
        /// <inheritdoc />
        public override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            ODataProperty property = item as ODataProperty;

            if (property != null)
            {
                item = property.Value;
            }

            IEdmEnumTypeReference enumTypeReference = edmType.AsEnum();
            ODataEnumValue        enumValue         = item as ODataEnumValue;

            if (readContext.IsUntyped)
            {
                Contract.Assert(edmType.TypeKind() == EdmTypeKind.Enum);
                return(new EdmEnumObject(enumTypeReference, enumValue.Value));
            }

            IEdmEnumType enumType = enumTypeReference.EnumDefinition();

            // Enum member supports model alias case. So, try to use the Edm member name to retrieve the Enum value.
            var memberMapAnnotation = readContext.Model.GetClrEnumMemberAnnotation(enumType);

            if (memberMapAnnotation != null)
            {
                if (enumValue != null)
                {
                    IEdmEnumMember enumMember = enumType.Members.FirstOrDefault(m => m.Name == enumValue.Value);
                    if (enumMember != null)
                    {
                        var clrMember = memberMapAnnotation.GetClrEnumMember(enumMember);
                        if (clrMember != null)
                        {
                            return(clrMember);
                        }
                    }
                }
            }

            Type clrType = EdmLibHelpers.GetClrType(edmType, readContext.Model);

            return(EnumDeserializationHelpers.ConvertEnumValue(item, clrType));
        }
Esempio n. 29
0
        /// <inheritdoc />
        public sealed override object ReadInline(object item, IEdmTypeReference edmType, ODataDeserializerContext readContext)
        {
            if (item == null)
            {
                return(null);
            }

            if (readContext.IsUntyped)
            {
                Contract.Assert(edmType.TypeKind() == EdmTypeKind.Enum);
                return(new EdmEnumObject((IEdmEnumTypeReference)edmType, ((ODataEnumValue)item).Value));
            }
            Type clrType = EdmLibHelpers.GetClrType(edmType, readContext.Model);

            return(EnumDeserializationHelpers.ConvertEnumValue(item, clrType));
        }
Esempio n. 30
0
        private Expression BindSingleResourceCastFunctionCall(SingleResourceFunctionCallNode node)
        {
            Contract.Assert(ClrCanonicalFunctions.CastFunctionName == node.Name);

            Expression[] arguments = BindArguments(node.Parameters);

            Contract.Assert(arguments.Length == 2);

            string   targetEdmTypeName = (string)((ConstantNode)node.Parameters.Last()).Value;
            IEdmType targetEdmType     = Model.FindType(targetEdmTypeName);
            Type     targetClrType     = null;

            if (targetEdmType != null)
            {
                targetClrType = EdmLibHelpers.GetClrType(targetEdmType.ToEdmTypeReference(false), Model);
            }

            if (arguments[0].Type == targetClrType)
            {
                // We only support to cast Entity type to the same type now.
                return(arguments[0]);
            }
            else if (arguments[0].Type.IsAssignableFrom(targetClrType))
            {
                // To support to cast Entity/Complex type to the sub type now.
                Expression source;
                if (node.Source != null)
                {
                    source = BindCastSourceNode(node.Source);
                }
                else
                {
                    // if the cast is on the root i.e $it (~/Products?$filter=NS.PopularProducts/.....),
                    // node.Source would be null. Calling BindCastSourceNode will always return '$it'.
                    // In scenarios where we are casting a navigation property to return an expression that queries against the parent property,
                    // we need to have a memberAccess expression e.g '$it.Category'. We can get this from arguments[0].
                    source = arguments[0];
                }
                return(Expression.TypeAs(source, targetClrType));
            }
            else
            {
                // Cast fails and return null.
                return(NullConstant);
            }
        }