Esempio n. 1
0
        /// <summary>
        /// Apply orderby to the given resouce expression
        /// </summary>
        /// <param name="rootExpression"></param>
        /// <param name="entityInstanceType"></param>
        /// <param name="uriParser"></param>
        /// <param name="orderByClause"></param>
        /// <returns></returns>
        public static Expression ApplyOrderBy(this Expression rootExpression, Type entityInstanceType, ODataUriParser uriParser, OrderByClause orderByClause)
        {
            ParameterExpression        parameter = Expression.Parameter(entityInstanceType, "it");
            NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator()
            {
                ImplicitVariableParameterExpression = parameter,
                UriParser = uriParser,
            };

            Expression orderByNodeExpression = nodeToExpressionTranslator.TranslateNode(orderByClause.Expression);

            var keyType = EdmClrTypeUtils.GetInstanceType(orderByClause.Expression.TypeReference);

            if (orderByClause.Expression.TypeReference.IsNullable && keyType.IsValueType)
            {
                keyType = typeof(Nullable <>).MakeGenericType(keyType);
            }

            var method = orderByClause.Direction == OrderByDirection.Ascending ? "OrderBy" : "OrderByDescending";
            //OrderBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
            var expression = Expression.Call(
                typeof(Enumerable),
                method,
                new Type[] { entityInstanceType, keyType },
                rootExpression,
                Expression.Lambda(orderByNodeExpression, parameter)) as Expression;
            var thenBy = orderByClause.ThenBy;

            while (null != thenBy)
            {
                expression = expression.ApplyThenBy(entityInstanceType, uriParser, thenBy);
                thenBy     = thenBy.ThenBy;
            }
            return(expression);
        }
Esempio n. 2
0
        /// <summary>
        /// Translate a single entity cast access to expression
        /// </summary>
        /// <param name="sourceNode">The source of single entity cast access.</param>
        /// <param name="typeReference">The target type reference of casting.</param>
        /// <returns></returns>
        private Expression TranslateSingleValueCastAccess(QueryNode sourceNode, IEdmTypeReference typeReference)
        {
            Expression source     = this.TranslateNode(sourceNode);
            Type       targetType = EdmClrTypeUtils.GetInstanceType(typeReference);

            return(Expression.TypeAs(source, targetType));
        }
Esempio n. 3
0
        private Type GetElementTypeForOption(string option)
        {
            if (this.Target.ElementTypeKind == EdmTypeKind.None)
            {
                throw Utility.BuildException(
                          HttpStatusCode.BadRequest,
                          string.Format("The query option '{0}' can only be applied to collection resouces", option),
                          null);
            }

            return(EdmClrTypeUtils.GetInstanceType(this.Target.ElementType.FullTypeName()));
        }
Esempio n. 4
0
        /// <summary>
        /// Translate KeySegment to linq expression.
        /// </summary>
        /// <param name="segment">The KeySegment</param>
        /// <returns>The linq expression</returns>
        public override Expression Translate(KeySegment segment)
        {
            if (!(this.LastProcessedSegment is EntitySetSegment || this.LastProcessedSegment is NavigationPropertySegment || this.LastProcessedSegment is NavigationPropertyLinkSegment))
            {
                throw new InvalidOperationException("Unsupported URI segment before KeySegment");
            }

            // translate to be ResultExpressionFromEntitySetSegment.Where(id -> id == keyVale).Single()
            IEdmEntityType entityType   = segment.EdmType as IEdmEntityType;
            Type           instanceType = EdmClrTypeUtils.GetInstanceType(entityType.FullTypeName());

            // Convert to .Where(it=> it is Type)
            ParameterExpression parameter = Expression.Parameter(instanceType, "it");
            Expression          body      = null;

            foreach (var key in segment.Keys)
            {
                Expression keyPredicate             = null;
                var        propertyAccessExpression = Expression.Property(parameter, instanceType, key.Key);

                var keyType = entityType.Key().Single(k => k.Name == key.Key).Type;
                if (keyType.IsTypeDefinition())
                {
                    var typeDefinition = keyType.AsTypeDefinition();
                    var underlyingType = EdmClrTypeUtils.GetInstanceType(typeDefinition.TypeDefinition().UnderlyingType.FullTypeName());
                    keyPredicate = Expression.Equal(Expression.Convert(propertyAccessExpression, underlyingType), Expression.Constant(key.Value));
                }
                else
                {
                    keyPredicate = Expression.Equal(propertyAccessExpression, Expression.Constant(key.Value));
                }

                if (body == null)
                {
                    body = keyPredicate;
                }
                else
                {
                    body = Expression.AndAlso(body, keyPredicate);
                }
            }

            this.ResultExpression = Expression.Call(
                this.ResultExpression,
                typeof(EntityCollection <>).MakeGenericType(instanceType).GetMethod("GetEntity"),
                Expression.Lambda(body, parameter));

            this.LastProcessedSegment = segment;
            return(this.ResultExpression);
        }
        /// <summary>
        /// Visit a CountNode
        /// </summary>
        /// <param name="nodeIn">The node to visit</param>
        /// <returns>The translated expression</returns>
        public override Expression Visit(CountNode nodeIn)
        {
            this.CheckArgumentNull(nodeIn, "CountNode");

            Type       propType = null;
            Expression propExpr = null;

            // Element of collection could be primitive type or enum or complex or entity type
            if (nodeIn.Source.ItemType.IsPrimitive() || nodeIn.Source.ItemType.IsEnum())
            {
                var collection = (CollectionPropertyAccessNode)nodeIn.Source;
                propExpr = Visit(collection);
                var def = collection.Property.Type.AsCollection();
                propType = EdmClrTypeUtils.GetInstanceType(def.ElementType());
            }
            else if ((nodeIn.Source.ItemType.IsComplex() && nodeIn.Source.Kind.Equals(QueryNodeKind.CollectionComplexNode)))
            {
                // This does not handle complex collection cast case, if it is a complex collection cast, the Kind will be CollectionComplexCast and node.Source is CollectionComplexCastNode
                var collection = (CollectionComplexNode)nodeIn.Source;
                propExpr = Visit(collection);
                var def = collection.Property.Type.AsCollection();
                propType = EdmClrTypeUtils.GetInstanceType(def.ElementType());
            }
            else if (nodeIn.Source.ItemType.IsEntity() &&
                     nodeIn.Source.Kind.Equals(QueryNodeKind.CollectionNavigationNode))
            {
                // This does not handle entity collection cast case, if it is a entity collection cast, the Kind will be CollectionResourceCast and node.Source is CollectionResourceCastNode
                var collection = (CollectionNavigationNode)nodeIn.Source;
                propExpr = Visit(collection);
                var def = collection.NavigationProperty.Type.AsCollection();
                propType = EdmClrTypeUtils.GetInstanceType(def.ElementType());
            }
            else
            {
                // Should no such case as collection item is either primitive or enum or complex or entity.
                throw new NotSupportedException(
                          string.Format(
                              "Filter based on count of collection with item of type {0} is not supported yet.",
                              nodeIn.Source.ItemType));
            }

            // Per standard, collection can not be null, but could be an empty collection, so null is not considered here.
            var        asQuerableMethod     = _queryableAsQueryableMethod.MakeGenericMethod(propType);
            Expression asQuerableExpression = Expression.Call(null, asQuerableMethod, propExpr);

            var countMethod     = _countMethod.MakeGenericMethod(propType);
            var countExpression = Expression.Call(null, countMethod, asQuerableExpression);

            return(countExpression);
        }
Esempio n. 6
0
        /// <summary>
        /// Visit a ConvertNode
        /// </summary>
        /// <param name="nodeIn">The node to visit</param>
        /// <returns>The translated expression</returns>
        public override Expression Visit(ConvertNode nodeIn)
        {
            this.CheckArgumentNull(nodeIn, "ConvertNode");
            var sourceExpression = this.TranslateNode(nodeIn.Source);

            var targetEdmType = nodeIn.TypeReference;

            if (null == targetEdmType)
            {
                //Open property's target type is null, so return the source expression directly, supposely the caller should be ready to handle data of Object type.
                return(sourceExpression);
            }
            var targetClrType = EdmClrTypeUtils.GetInstanceType(targetEdmType);

            return(Expression.Convert(sourceExpression, targetClrType));
        }
Esempio n. 7
0
        /// <summary>
        /// Translate CountSegment to linq expression.
        /// </summary>
        /// <param name="segment">The CountSegment</param>
        /// <returns>The linq expression</returns>
        public override Expression Translate(CountSegment segment)
        {
            if (!(this.LastProcessedSegment is EntitySetSegment || this.LastProcessedSegment is NavigationPropertySegment))
            {
                throw new InvalidOperationException("Unsupported URI segment before CountSegment");
            }

            Type instanceType = EdmClrTypeUtils.GetInstanceType((this.LastProcessedSegment.EdmType as EdmCollectionType).ElementType);

            // A set return now is a IEnumable, try to convert to IQueryable.
            this.ResultExpression = Expression.Call(typeof(Queryable), AsQueryableMethod, new Type[] { instanceType }, this.ResultExpression);

            this.ResultExpression     = Expression.Call(typeof(Queryable), CountMethodName, new Type[] { instanceType }, this.ResultExpression);
            this.LastProcessedSegment = segment;
            return(this.ResultExpression);
        }
Esempio n. 8
0
        /// <summary>
        /// Visit a ConstantNode
        /// </summary>
        /// <param name="nodeIn">The node to visit</param>
        /// <returns>The translated expression</returns>
        public override Expression Visit(ConstantNode nodeIn)
        {
            this.CheckArgumentNull(nodeIn, "ConstantNode");
            if (null == nodeIn.Value)
            {
                return(Expression.Constant(null));
            }

            // collection of entity
            if (nodeIn.TypeReference != null && nodeIn.TypeReference.IsCollection() &&
                (nodeIn.TypeReference.Definition as IEdmCollectionType).ElementType.IsEntity())
            {
                return(Expression.Constant(ParseEntityCollection(nodeIn)));
            }

            // the value is entity or entity reference.
            if (nodeIn.TypeReference != null && nodeIn.TypeReference.IsEntity())
            {
                return(Expression.Constant(ParseEntity(nodeIn)));
            }
            // the value is complex or collection.
            if (nodeIn.Value is ODataComplexValue || nodeIn.Value is ODataCollectionValue || nodeIn.Value is ODataEntry)
            {
                object value = ODataObjectModelConverter.ConvertPropertyValue(nodeIn.Value);
                return(Expression.Constant(value));
            }

            // the value is enum
            if (nodeIn.TypeReference.IsEnum())
            {
                ODataEnumValue enumValue  = (ODataEnumValue)nodeIn.Value;
                object         enumClrVal = Enum.Parse(EdmClrTypeUtils.GetInstanceType(enumValue.TypeName), enumValue.Value);
                return(Expression.Constant(enumClrVal, EdmClrTypeUtils.GetInstanceType(nodeIn.TypeReference)));
            }

            // the value is primitive
            Type targetType = nodeIn.Value.GetType();

            if (nodeIn.TypeReference.IsSpatial())
            {
                targetType = GetPublicSpatialBaseType(nodeIn.Value);
            }

            return(Expression.Constant(nodeIn.Value, targetType));
        }
Esempio n. 9
0
        /// <summary>
        /// Translate TypeSegment to linq expression.
        /// </summary>
        /// <param name="segment">The TypeSegment</param>
        /// <returns>The linq expression</returns>
        public override Expression Translate(TypeSegment segment)
        {
            if (this.LastQueryTarget.IsEntitySet)
            {
                Type baseType     = EdmClrTypeUtils.GetInstanceType(this.LastQueryTarget.ElementType.FullTypeName());
                Type instanceType = EdmClrTypeUtils.GetInstanceType(((IEdmCollectionType)segment.EdmType).ElementType);

                // A set return now is a IEnumable, try to convert to IQueryable.
                this.ResultExpression = Expression.Call(typeof(Queryable), AsQueryableMethod, new Type[] { baseType }, this.ResultExpression);

                // Convert to .Where(it=> it is Type)
                ParameterExpression parameter = Expression.Parameter(baseType, "it");
                Expression          body      = Expression.TypeIs(parameter, instanceType);
                this.ResultExpression = Expression.Call(typeof(Queryable), WhereMethodName, new Type[] { baseType }, this.ResultExpression, Expression.Quote(Expression.Lambda(body, parameter)));
                this.ResultExpression = Expression.Call(typeof(Queryable), CastMethodName, new[] { instanceType }, this.ResultExpression);
            }
            else if (this.LastQueryTarget.TypeKind == EdmTypeKind.Entity)
            {
                Type instanceType = EdmClrTypeUtils.GetInstanceType(segment.EdmType.FullTypeName());
                this.ResultExpression = Expression.Convert(this.ResultExpression, instanceType);
            }
            else if (this.LastQueryTarget.Property != null)
            {
                if (this.LastQueryTarget.TypeKind == EdmTypeKind.Complex)
                {
                    Type instanceType = EdmClrTypeUtils.GetInstanceType(segment.EdmType.FullTypeName());
                    this.ResultExpression = Expression.Convert(this.ResultExpression, instanceType);
                }
                else
                {
                    // This code should not be hit. It should be prevented by UriParser.
                    throw new ApplicationException(
                              string.Format("PropertySegment with TypeKind '{0}' following by TypeSegment is invalid", this.LastQueryTarget.TypeKind));
                }
            }
            else
            {
                throw Utility.BuildException(HttpStatusCode.NotImplemented, "Unsupported URI segment before TypeSegment", null);
            }

            this.LastProcessedSegment = segment;
            return(this.ResultExpression);
        }
Esempio n. 10
0
        /// <summary>
        /// Visit an AnyNode
        /// </summary>
        /// <param name="nodeIn">The node to visit</param>
        /// <returns>The translated expression</returns>
        public override Expression Visit(AnyNode nodeIn)
        {
            var instanceType = EdmClrTypeUtils.GetInstanceType(nodeIn.RangeVariables[0].TypeReference);
            ParameterExpression        parameter = Expression.Parameter(instanceType, nodeIn.RangeVariables[0].Name);
            NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator()
            {
                ImplicitVariableParameterExpression = parameter,
                UriParser  = this.UriParser,
                DataSource = this.DataSource,
            };
            Expression conditionExpression = nodeToExpressionTranslator.TranslateNode(nodeIn.Body);
            Expression rootExpression      = this.TranslateNode(nodeIn.Source);

            return(Expression.Call(
                       typeof(Enumerable),
                       "Any",
                       new Type[] { instanceType },
                       rootExpression,
                       Expression.Lambda(conditionExpression, parameter)));
        }
Esempio n. 11
0
        /// <summary>
        /// Translate NavigationPropertyLinkSegment to linq expression.
        /// </summary>
        /// <param name="segment">The NavigationPropertyLinkSegment</param>
        /// <returns>The linq expression</returns>
        public override Expression Translate(NavigationPropertyLinkSegment segment)
        {
            if (!(this.LastProcessedSegment is KeySegment ||
                  this.LastProcessedSegment is SingletonSegment ||
                  this.LastProcessedSegment is TypeSegment))
            {
                throw new InvalidOperationException("Unsupported URI segment before NavigationPropertyLinkSegment");
            }

            var lastSegmentEntityType = this.LastProcessedSegment.EdmType as EdmEntityType;

            // <context>/PropertyName will be translated to <context>.PropertyName
            this.ResultExpression = Expression.Property(
                this.ResultExpression,
                EdmClrTypeUtils.GetInstanceType(lastSegmentEntityType.FullTypeName()),
                segment.NavigationProperty.Name);

            this.LastProcessedSegment = segment;
            return(this.ResultExpression);
        }
Esempio n. 12
0
        /// <summary>
        /// Handle an ExpandedReferenceSelectItem
        /// </summary>
        /// <param name="item">the item to Handle</param>
        public override void Handle(ExpandedReferenceSelectItem item)
        {
            var navigationProperty = (item.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty;

            this.ExpandedChildElement = this.ParentElement.GetType().GetProperty(navigationProperty.Name).GetValue(this.ParentElement, null);

            if (this.ExpandedChildElement is IEnumerable)
            {
                var        entityInstanceType = EdmClrTypeUtils.GetInstanceType(item.NavigationSource.EntityType().FullName());
                Expression resultExpression   = (this.ExpandedChildElement as IEnumerable).AsQueryable().Expression;

                if (item.FilterOption != null)
                {
                    resultExpression = resultExpression.ApplyFilter(entityInstanceType, null, item.FilterOption);
                }

                if (item.SearchOption != null)
                {
                    resultExpression = resultExpression.ApplySearch(entityInstanceType, null, item.SearchOption);
                }

                if (item.OrderByOption != null)
                {
                    resultExpression = resultExpression.ApplyOrderBy(entityInstanceType, null, item.OrderByOption);
                }

                if (item.SkipOption.HasValue)
                {
                    resultExpression = resultExpression.ApplySkip(entityInstanceType, item.SkipOption.Value);
                }

                if (item.TopOption.HasValue)
                {
                    resultExpression = resultExpression.ApplyTop(entityInstanceType, item.TopOption.Value);
                }

                Expression <Func <object> > lambda = Expression.Lambda <Func <object> >(resultExpression);
                Func <object> compiled             = lambda.Compile();
                this.ExpandedChildElement = compiled() as IEnumerable;
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Apply thenOrderBy to the given resouce expression
        /// </summary>
        /// <param name="rootExpression"></param>
        /// <param name="entityInstanceType"></param>
        /// <param name="uriParser"></param>
        /// <param name="thenBy"></param>
        /// <returns></returns>
        public static Expression ApplyThenBy(this Expression rootExpression, Type entityInstanceType, ODataUriParser uriParser, OrderByClause thenBy)
        {
            ParameterExpression        parameter = Expression.Parameter(entityInstanceType, "it");
            NodeToExpressionTranslator nodeToExpressionTranslator = new NodeToExpressionTranslator()
            {
                ImplicitVariableParameterExpression = parameter,
                UriParser = uriParser,
            };
            Expression orderByNodeExpression = nodeToExpressionTranslator.TranslateNode(thenBy.Expression);

            var keyType = EdmClrTypeUtils.GetInstanceType(thenBy.Expression.TypeReference);
            var method  = thenBy.Direction == OrderByDirection.Ascending ? "ThenBy" : "ThenByDescending";

            //ThenBy<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector)
            return(Expression.Call(
                       typeof(Enumerable),
                       method,
                       new Type[] { entityInstanceType, keyType },
                       rootExpression,
                       Expression.Lambda(orderByNodeExpression, parameter)));
        }
Esempio n. 14
0
        public static object CreateResource(IEdmType type)
        {
            var targetType = EdmClrTypeUtils.GetInstanceType(type.FullTypeName());

            return(QuickCreateInstance(targetType));
        }
Esempio n. 15
0
        public static object ConvertPropertyValue(object propertyValue)
        {
            if (propertyValue == null)
            {
                return(null);
            }

            if (propertyValue is ODataEnumValue)
            {
                ODataEnumValue enumValue = (ODataEnumValue)propertyValue;
                return(Enum.Parse(EdmClrTypeUtils.GetInstanceType(enumValue.TypeName), enumValue.Value));
            }

            if (propertyValue is ODataCollectionValue)
            {
                ODataCollectionValue collection = (ODataCollectionValue)propertyValue;
                IList collectionList            = null;
                foreach (object odataItem in collection.Items)
                {
                    var item = ConvertPropertyValue(odataItem);
                    if (collectionList == null)
                    {
                        Type listType = string.IsNullOrEmpty(collection.TypeName) ? null : EdmClrTypeUtils.GetInstanceType(collection.TypeName);
                        if (listType == null)
                        {
                            Type itemType = item.GetType();
                            listType = typeof(List <>).MakeGenericType(new[] { itemType });
                        }
                        collectionList = (IList)Utility.QuickCreateInstance(listType);
                    }

                    collectionList.Add(item);
                }
                return(collectionList);
            }

            if (propertyValue is ODataResource)
            {
                ODataResource entry       = (ODataResource)propertyValue;
                var           type        = EdmClrTypeUtils.GetInstanceType(entry.TypeName);
                var           newInstance = Utility.QuickCreateInstance(type);
                foreach (var p in entry.Properties)
                {
                    PropertyInfo targetProperty = type.GetProperty(p.Name);
                    // If the value is a odata collection value that contains no element, set the value to a empty collection.
                    // ConvertPropertyValue won't work here because it could not know what the type it its.
                    var collectionValue = p.Value as ODataCollectionValue;
                    if (collectionValue != null && !collectionValue.Items.Cast <object>().Any())
                    {
                        targetProperty.SetValue(newInstance, Utility.QuickCreateInstance(targetProperty.PropertyType), new object[] { });
                    }
                    else
                    {
                        targetProperty.SetValue(newInstance, ConvertPropertyValue(p.Value), new object[] { });
                    }
                }

                return(newInstance);
            }

            return(propertyValue);
        }
Esempio n. 16
0
        public static object ReadEntityOrEntityCollection(ODataReader reader, bool forFeed)
        {
            MethodInfo addMethod = null;

            // Store the last entry of the top-level feed or the top-level entry;
            ODataResource entry = null;

            // Store entries at each level
            Stack <ODataItem> items = new Stack <ODataItem>();

            // Store the objects with its parent for current level.
            // Example:
            //    CompleCollection: [ complex1, complex2 ]
            //    objects contains [{CompleCollection, complex1Obj}, {CompleCollection, complex2Obj}] when NestedResourceInfoEnd for CompleCollection
            Stack <KeyValuePair <ODataItem, object> > objects = new Stack <KeyValuePair <ODataItem, object> >();

            // Store the SetValue action for complex property.
            Stack <KeyValuePair <ODataItem, Action <object> > > actions = new Stack <KeyValuePair <ODataItem, Action <object> > >();

            while (reader.Read())
            {
                switch (reader.State)
                {
                case ODataReaderState.ResourceStart:
                case ODataReaderState.NestedResourceInfoStart:
                {
                    items.Push(reader.Item);
                    break;
                }

                case ODataReaderState.NestedResourceInfoEnd:
                {
                    items.Pop();
                    // Create current complex property value.
                    var currentProperty = reader.Item as ODataNestedResourceInfo;
                    var parent          = items.Peek() as ODataResource;
                    var parentType      = EdmClrTypeUtils.GetInstanceType(parent.TypeName);
                    var propertyInfo    = parentType.GetProperty(currentProperty.Name);
                    if (propertyInfo != null)
                    {
                        var propertyType = propertyInfo.PropertyType;
                        if (propertyType.IsGenericType)
                        {
                            Type listType = typeof(List <>).MakeGenericType(propertyType.GetGenericArguments()[0]);
                            addMethod = listType.GetMethod("Add");
                            var currentList = Activator.CreateInstance(listType);
                            while (objects.Count > 0 && objects.Peek().Key == currentProperty)
                            {
                                addMethod.Invoke(currentList, new[] { objects.Pop().Value });
                            }

                            // Keep the order of all the items
                            MethodInfo reverseMethod = listType.GetMethod("Reverse", new Type[0]);
                            reverseMethod.Invoke(currentList, new object[0]);
                            actions.Push(new KeyValuePair <ODataItem, Action <object> >(parent, obj => propertyInfo.SetValue(obj, currentList)));
                        }
                        else
                        {
                            var propertyValue = objects.Pop().Value;
                            actions.Push(new KeyValuePair <ODataItem, Action <object> >(parent, obj => propertyInfo.SetValue(obj, propertyValue)));
                        }
                    }

                    break;
                }

                case ODataReaderState.ResourceEnd:
                {
                    // Create object for current resource.
                    entry = reader.Item as ODataResource;
                    object item = ODataObjectModelConverter.ConvertPropertyValue(entry);
                    while (actions.Count > 0 && actions.Peek().Key == entry)
                    {
                        actions.Pop().Value.Invoke(item);
                    }

                    items.Pop();
                    var parent = items.Count > 0 ? items.Peek() : null;
                    objects.Push(new KeyValuePair <ODataItem, object>(parent, item));
                    break;
                }

                default:
                    break;
                }
            }
            if (forFeed)
            {
                // create the list. This would require the first type is not derived type.
                List <object> topLeveObjects = new List <object>();
                while (objects.Count > 0)
                {
                    topLeveObjects.Add(objects.Pop().Value);
                }

                Type type = null;
                // Need to fix this if all items in the collection are null;
                if (entry == null || string.IsNullOrEmpty(entry.TypeName))
                {
                    for (int i = 0; i < topLeveObjects.Count; i++)
                    {
                        if (topLeveObjects[i] != null)
                        {
                            type = topLeveObjects[i].GetType();
                            break;
                        }
                    }
                }
                else
                {
                    type = EdmClrTypeUtils.GetInstanceType(entry.TypeName);
                }

                Type listType = typeof(List <>).MakeGenericType(type);
                addMethod = listType.GetMethod("Add");
                var list = Activator.CreateInstance(listType);
                for (int i = topLeveObjects.Count - 1; i >= 0; i--)
                {
                    addMethod.Invoke(list, new[] { topLeveObjects[i] });
                }

                return(list);
            }
            else
            {
                return(objects.Pop().Value);
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Parse the constant entity collection node.
        /// </summary>
        /// <param name="nodeIn">The input constant node.</param>
        /// <returns>The parsed object.</returns>
        private object ParseEntityCollection(ConstantNode nodeIn)
        {
            ODataMessageReaderSettings settings = new ODataMessageReaderSettings();
            InMemoryMessage            message  = new InMemoryMessage()
            {
                Stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(nodeIn.LiteralText)),
            };

            var entityType =
                ((nodeIn.TypeReference.Definition as IEdmCollectionType).ElementType as IEdmEntityTypeReference)
                .Definition as IEdmEntityType;
            object     list      = null;
            MethodInfo addMethod = null;

            using (
                ODataMessageReader reader = new ODataMessageReader(message as IODataRequestMessage, settings,
                                                                   this.UriParser.Model))
            {
                if (nodeIn.LiteralText.Contains("@odata.id"))
                {
                    ODataEntityReferenceLinks referenceLinks = reader.ReadEntityReferenceLinks();
                    foreach (var referenceLink in referenceLinks.Links)
                    {
                        var queryContext = new QueryContext(this.UriParser.ServiceRoot, referenceLink.Url,
                                                            this.DataSource.Model);
                        var target = queryContext.ResolveQuery(this.DataSource);

                        if (list == null)
                        {
                            // create the list. This would require the first type is not derived type.
                            Type listType = typeof(List <>).MakeGenericType(target.GetType());
                            addMethod = listType.GetMethod("Add");
                            list      = Activator.CreateInstance(listType);
                        }

                        addMethod.Invoke(list, new[] { target });
                    }

                    return(list);
                }

                var feedReader = reader.CreateODataFeedReader(
                    new EdmEntitySet(new EdmEntityContainer("NS", "Test"), "TestType", entityType),
                    entityType);
                ODataEntry entry = null;
                while (feedReader.Read())
                {
                    if (feedReader.State == ODataReaderState.EntryEnd)
                    {
                        entry = feedReader.Item as ODataEntry;
                        object item = ODataObjectModelConverter.ConvertPropertyValue(entry);


                        if (list == null)
                        {
                            // create the list. This would require the first type is not derived type.
                            var  type     = EdmClrTypeUtils.GetInstanceType(entry.TypeName);
                            Type listType = typeof(List <>).MakeGenericType(type);
                            addMethod = listType.GetMethod("Add");
                            list      = Activator.CreateInstance(listType);
                        }

                        addMethod.Invoke(list, new[] { item });
                    }
                }
                return(list);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Translates a function call into a corresponding <see cref="Expression"/>.
        /// </summary>
        /// <param name="functionName">Name of the function.</param>
        /// <param name="argumentNodes">The argument nodes.</param>
        /// <returns>
        /// The translated expression.
        /// </returns>
        private Expression TranslateFunctionCall(string functionName, IEnumerable <QueryNode> argumentNodes)
        {
            switch (functionName)
            {
                #region string functions
            case "contains":
                var methodInfoOfContains = typeof(string).GetMethod("Contains", BindingFlags.Public | BindingFlags.Instance);
                var instanceOfContains   = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfContains   = argumentNodes.ElementAt(1).Accept(this);
                return(Expression.Call(instanceOfContains, methodInfoOfContains, argumentOfContains));

            case "endswith":
                var methodInfoOfEndsWith = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
                var instanceOfEndsWith   = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfEndsWith   = argumentNodes.ElementAt(1).Accept(this);
                return(Expression.Call(instanceOfEndsWith, methodInfoOfEndsWith, argumentOfEndsWith));

            case "startswith":
                var methodInfoOfStartsWith = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
                var instanceOfStartsWith   = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfStartsWith   = argumentNodes.ElementAt(1).Accept(this);
                return(Expression.Call(instanceOfStartsWith, methodInfoOfStartsWith, argumentOfStartsWith));

            case "length":
                var propertyInfoOfLength = typeof(string).GetProperty("Length", typeof(int));
                var instanceOfLength     = argumentNodes.ElementAt(0).Accept(this);
                return(Expression.Property(instanceOfLength, propertyInfoOfLength));

            case "indexof":
                var methodInfoOfIndexOf = typeof(string).GetMethod("IndexOf", new Type[] { typeof(string) });
                var instanceOfIndexOf   = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfIndexOf   = argumentNodes.ElementAt(1).Accept(this);
                return(Expression.Call(instanceOfIndexOf, methodInfoOfIndexOf, argumentOfIndexOf));

            case "substring":
                var argumentCount = argumentNodes.Count();
                if (argumentNodes.Count() == 2)
                {
                    var methodInfoOfSubString = typeof(string).GetMethod("Substring", new Type[] { typeof(int) });
                    var instanceOfSubString   = argumentNodes.ElementAt(0).Accept(this);
                    var argumentOfSubString   = argumentNodes.ElementAt(1).Accept(this);
                    return(Expression.Call(instanceOfSubString, methodInfoOfSubString, argumentOfSubString));
                }
                else if (argumentNodes.Count() == 3)
                {
                    var methodInfoOfSubString = typeof(string).GetMethod("Substring", new Type[] { typeof(int), typeof(int) });
                    var instanceOfSubString   = argumentNodes.ElementAt(0).Accept(this);
                    var argumentOfSubString   = argumentNodes.ElementAt(1).Accept(this);
                    var argumentOfSubString2  = argumentNodes.ElementAt(2).Accept(this);
                    return(Expression.Call(instanceOfSubString, methodInfoOfSubString, argumentOfSubString, argumentOfSubString2));
                }
                else
                {
                    throw new ArgumentException("argumentNodes");
                }

            case "tolower":
                var methodInfoOfToLower = typeof(string).GetMethod("ToLower", new Type[] { });
                var instanceOfToLower   = argumentNodes.ElementAt(0).Accept(this);
                return(Expression.Call(instanceOfToLower, methodInfoOfToLower));

            case "toupper":
                var methodInfoOfToUpper = typeof(string).GetMethod("ToUpper", new Type[] { });
                var instanceOfToUpper   = argumentNodes.ElementAt(0).Accept(this);
                return(Expression.Call(instanceOfToUpper, methodInfoOfToUpper));

            case "trim":
                var methodInfoOfTrim = typeof(string).GetMethod("Trim", new Type[] { });
                var instanceOfTrim   = argumentNodes.ElementAt(0).Accept(this);
                return(Expression.Call(instanceOfTrim, methodInfoOfTrim));

            case "concat":
                var methodInfoOfConcat = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
                var argumentOfConcat1  = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfConcat2  = argumentNodes.ElementAt(1).Accept(this);
                return(Expression.Call(methodInfoOfConcat, argumentOfConcat1, argumentOfConcat2));

                #endregion

                #region DateTime Method
            case "year":
                return(TranslateDateTimeInstanceProperty("Year", argumentNodes));

            case "month":
                return(TranslateDateTimeInstanceProperty("Month", argumentNodes));

            case "day":
                return(TranslateDateTimeInstanceProperty("Day", argumentNodes));

            case "hour":
                return(TranslateDateTimeInstanceProperty("Hour", argumentNodes));

            case "minute":
                return(TranslateDateTimeInstanceProperty("Minute", argumentNodes));

            case "second":
                return(TranslateDateTimeInstanceProperty("Second", argumentNodes));

                // Don't support those type by now.
                //case "fractionalseconds":
                //    return TranslateDateTimeInstanceProperty("Millisecond", argumentNodes);
                //case "date":
                //    return TranslateDateTimeInstanceProperty("Date", argumentNodes);
                //case "time":
                //    return TranslateDateTimeProperty("Year");
                //case "totaloffsetminutes":
                //    return TranslateDateTimeProperty("Date", argumentNodes);
                //case "now":
                //    return TranslateDateTimeProperty("Now", argumentNodes);
                //case "mindatetime":
                //    return TranslateDateTimeProperty("MinValue", argumentNodes);
                //case "maxdatetime":
                //    return TranslateDateTimeProperty("MaxValue", argumentNodes);
                #endregion

                #region Math Methods
            case "round":
                return(TranslateMathFunction("Round", argumentNodes));

            case "floor":
                return(TranslateMathFunction("Floor", argumentNodes));

            case "ceiling":
                return(TranslateMathFunction("Ceiling", argumentNodes));

                #endregion

                #region Type Functions
            case "cast":
                var instanceOfCast   = argumentNodes.ElementAt(0).Accept(this);
                var typeInfoOfCast   = (ConstantNode)argumentNodes.ElementAt(1);
                var targetTypeOfCast = EdmClrTypeUtils.GetInstanceType(typeInfoOfCast.Value.ToString());
                var methodInfoOfCast = typeof(TypeFunctionHelper).GetMethod("TypeCastFunction", BindingFlags.Public | BindingFlags.Static);
                methodInfoOfCast = methodInfoOfCast.MakeGenericMethod(new Type[] { targetTypeOfCast, instanceOfCast.Type });
                return(Expression.Call(methodInfoOfCast, instanceOfCast));

            case "isof":
                var instanceOfIsOf = argumentNodes.ElementAt(0).Accept(this);
                var typeInfoOfIsOf = (ConstantNode)argumentNodes.ElementAt(1);
                return(Expression.TypeIs(instanceOfIsOf, EdmClrTypeUtils.GetInstanceType(typeInfoOfIsOf.Value.ToString())));

                #endregion

                #region Geo Functions
            case "geo.distance":
                var argumentOfGeoDistance1  = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfGeoDistance2  = argumentNodes.ElementAt(1).Accept(this);
                var methodInfoOfGeoDistance = typeof(GeoFunctionHelper)
                                              .GetMethod("GetDistance", new Type[] { argumentOfGeoDistance1.Type, argumentOfGeoDistance2.Type });
                return(Expression.Call(methodInfoOfGeoDistance, argumentOfGeoDistance1, argumentOfGeoDistance2));

            case "geo.length":
                var argumentOfGeoLength   = argumentNodes.ElementAt(0).Accept(this);
                var methodInfoOfGeoLength = typeof(GeoFunctionHelper)
                                            .GetMethod("GetLength", new Type[] { argumentOfGeoLength.Type });
                return(Expression.Call(methodInfoOfGeoLength, argumentOfGeoLength));

            case "geo.intersects":
                var argumentOfGeoIntersects1   = argumentNodes.ElementAt(0).Accept(this);
                var argumentOfGeoIntersects2   = argumentNodes.ElementAt(1).Accept(this);
                var methodInfoOfGeoIntersectse = typeof(GeoFunctionHelper)
                                                 .GetMethod("GetIsIntersects", new Type[] { argumentOfGeoIntersects1.Type, argumentOfGeoIntersects2.Type });
                return(Expression.Call(methodInfoOfGeoIntersectse, argumentOfGeoIntersects1, argumentOfGeoIntersects2));

                #endregion
            default:
                throw new ArgumentException(functionName);
            }
        }