/// <summary>
        /// Converts an item from the data store into an ODataEntityReferenceLink.
        /// </summary>
        /// <param name="element">The item to convert.</param>
        /// <param name="navigationSource">The navigation source that the item belongs to.</param>
        /// <param name="targetVersion">The OData version this segment is targeting.</param>
        /// <returns>The converted ODataEntityReferenceLink represent with ODataEntry.</returns>
        public static ODataEntry ConvertToODataEntityReferenceLink(object element, IEdmNavigationSource entitySource, ODataVersion targetVersion)
        {
            IEdmStructuredType entityType = EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element) as IEdmStructuredType;

            if (entityType == null)
            {
                throw new InvalidOperationException("Can not create an entry for " + entitySource.Name);
            }

            var link = new ODataEntry();

            if (!string.IsNullOrEmpty(((ClrObject)element).EntitySetName) && entitySource is IEdmEntitySet && entityType is IEdmEntityType)
            {
                entitySource = new EdmEntitySet(((IEdmEntitySet)entitySource).Container, ((ClrObject)element).EntitySetName, (IEdmEntityType)entityType);
            }

            if (!(entitySource is IEdmContainedEntitySet))
            {
                Uri Url = BuildEntryUri(element, entitySource, targetVersion);
                link.Id = Url;
            }

            return(link);
        }
Пример #2
0
        public static object CreateResource(IEdmType type)
        {
            var targetType = EdmClrTypeUtils.GetInstanceType(type.FullTypeName());

            return(QuickCreateInstance(targetType));
        }
Пример #3
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);
            }
        }
Пример #4
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);
            }
        }
Пример #5
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);
            }
        }
Пример #6
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);
        }
Пример #7
0
        /// <summary>
        /// Converts an item from the data store into an ODataEntry.
        /// </summary>
        /// <param name="element">The item to convert.</param>
        /// <param name="navigationSource">The navigation source that the item belongs to.</param>
        /// <param name="targetVersion">The OData version this segment is targeting.</param>
        /// <returns>The converted ODataEntry.</returns>
        public static ODataResourceWrapper ConvertToODataEntry(object element, IEdmNavigationSource entitySource, ODataVersion targetVersion)
        {
            IEdmStructuredType entityType = EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element) as IEdmStructuredType;

            if (entityType == null)
            {
                throw new InvalidOperationException("Can not create an entry for " + entitySource.Name);
            }

            var propertiesOrNestedResourceInfos = GetPropertiesOrNestedResourceInfos(element, entityType);
            var entry = new ODataResource
            {
                Properties = propertiesOrNestedResourceInfos.OfType <ODataProperty>(),
            };

            var resourceWrapper = new ODataResourceWrapper()
            {
                Resource = entry,
                NestedResourceInfoWrappers = propertiesOrNestedResourceInfos.OfType <ODataNestedResourceInfoWrapper>().ToList(),
            };

            // Add Annotation in Entity Level
            if (((ClrObject)element).Annotations != null)
            {
                foreach (InstanceAnnotationType annotation in ((ClrObject)element).Annotations)
                {
                    if (string.IsNullOrEmpty(annotation.Target))
                    {
                        entry.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Name, annotation.ConvertValueToODataValue()));
                    }
                }
            }

            // Work around for entities from different entity set.
            if (!string.IsNullOrEmpty(((ClrObject)element).EntitySetName) && entitySource is IEdmEntitySet && entityType is IEdmEntityType)
            {
                entitySource = new EdmEntitySet(((IEdmEntitySet)entitySource).Container, ((ClrObject)element).EntitySetName, (IEdmEntityType)entityType);
            }

            string typeName;

            if (entityType is IEdmEntityType)
            {
                typeName = (entityType as IEdmEntityType).Name;
            }
            else if (entityType is IEdmComplexType)
            {
                typeName = (entityType as IEdmComplexType).Name;
            }
            else
            {
                throw new InvalidOperationException("Not Supported Edmtype to convert to OData Entry.");
            }
            entry.TypeName = element.GetType().Namespace + "." + typeName;

            // TODO: work around for now
            if (entitySource != null && !(entitySource is IEdmContainedEntitySet))
            {
                Uri entryUri = BuildEntryUri(element, entitySource, targetVersion);
                if (element.GetType().BaseType != null && entitySource.EntityType().Name != typeName)
                {
                    var editLink = new Uri(entryUri.AbsoluteUri.TrimEnd('/') + "/" + entry.TypeName);
                    entry.EditLink = editLink;
                    entry.ReadLink = editLink;
                }
                else
                {
                    entry.EditLink = entryUri;
                    entry.ReadLink = entryUri;
                }
                entry.Id = entryUri;
            }

            if (Utility.IsMediaEntity(element.GetType()))
            {
                var streamProvider = DataSourceManager.GetCurrentDataSource().StreamProvider;
                entry.MediaResource = new ODataStreamReferenceValue()
                {
                    ContentType = streamProvider.GetContentType(element),
                    ETag        = streamProvider.GetETag(element),
                };
            }

            return(resourceWrapper);
        }
Пример #8
0
        private static void WriteNavigationLinks(ODataWriter writer, object element, Uri parentEntryUri, IEdmNavigationSource edmParent, ODataVersion targetVersion, IEnumerable <SelectItem> expandedItems)
        {
            foreach (var navigationProperty in ((IEdmEntityType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, element)).NavigationProperties())
            {
                // give proprity to ExpandedReferenceSelectItem
                var expandedItem = GetExpandedReferenceItem(expandedItems, navigationProperty.Name);
                if (expandedItem == null)
                {
                    expandedItem = GetExpandedNavigationItem(expandedItems, navigationProperty.Name);
                }

                // For Atom, we always manually write out the links for the navigation properties off of the entity type
                // Or if the navigation is expanded, we manually write out the links for the navigation properties along with the expanded entries
                if (writer.GetType().Name != "ODataJsonLightWriter" || expandedItem != null)
                {
                    bool isCollection = navigationProperty.Type.IsCollection();

                    var navigationLink = new ODataNavigationLink
                    {
                        IsCollection = isCollection,
                        Name         = navigationProperty.Name,
                    };

                    if (writer.GetType().Name == "ODataAtomWriter")
                    {
                        //If the passed in parentEntryUri is null then exception will be thrown, to avoid this, create a relative 'potato' Uri.
                        navigationLink.Url = (parentEntryUri == null) ? new Uri("potato", UriKind.Relative) : new Uri(new Uri(parentEntryUri.AbsoluteUri + "/"), navigationProperty.Name);
                    }

                    writer.WriteStart(navigationLink);
                    if (expandedItem != null)
                    {
                        ExpandSelectItemHandler expandItemHandler = new ExpandSelectItemHandler(element);
                        expandedItem.HandleWith(expandItemHandler);

                        var propertyValue = expandItemHandler.ExpandedChildElement;

                        if (propertyValue != null)
                        {
                            IEdmNavigationSource targetSource = edmParent.FindNavigationTarget(navigationProperty);

                            if (isCollection)
                            {
                                long?count           = null;
                                var  collectionValue = propertyValue as IEnumerable;
                                if (collectionValue != null && expandedItem.CountOption == true)
                                {
                                    count = collectionValue.Cast <object>().LongCount();
                                }

                                if (expandedItem.GetType() == typeof(ExpandedReferenceSelectItem))
                                {
                                    WriteReferenceLinks(writer, collectionValue, targetSource as IEdmEntitySetBase, targetVersion, navigationLink);
                                }
                                else
                                {
                                    WriteFeed(writer, collectionValue, targetSource as IEdmEntitySetBase, targetVersion, ((ExpandedNavigationSelectItem)expandedItem).SelectAndExpand, count, null, null);
                                }
                            }
                            else
                            {
                                if (expandedItem.GetType() == typeof(ExpandedReferenceSelectItem))
                                {
                                    WriteReferenceLink(writer, propertyValue, targetSource, targetVersion, navigationLink);
                                }
                                else
                                {
                                    WriteEntry(writer, propertyValue, targetSource, targetVersion, ((ExpandedNavigationSelectItem)expandedItem).SelectAndExpand);
                                }
                            }
                        }
                    }
                    writer.WriteEnd();
                }
            }
        }
        public static object CreateODataValue(object value)
        {
            if (value != null)
            {
                Type t = value.GetType();
                if (t.IsGenericType)
                {
                    // Build a collection type property
                    string itemTypeName = t.GetGenericArguments().First().FullName;
                    if (itemTypeName == "System.UInt16" || itemTypeName == "System.UInt32" || itemTypeName == "System.UInt64")
                    {
                        string modelNS = DataSourceManager.GetCurrentDataSource().Model.DeclaredNamespaces.First();
                        itemTypeName = itemTypeName.Replace("System", modelNS);
                    }
                    else if (itemTypeName == "System.TimeSpan")
                    {
                        itemTypeName = "Edm.Duration";
                    }
                    else
                    {
                        itemTypeName = itemTypeName.Replace("System.", "Edm.");
                    }

                    var genericTypeName      = "Collection(" + itemTypeName + ")";
                    ICollection <object> tmp = new Collection <object>();
                    foreach (var o in (value as IEnumerable))
                    {
                        tmp.Add(CreateODataValue(o));
                    }
                    return(new ODataCollectionValue()
                    {
                        TypeName = genericTypeName, Items = tmp
                    });
                }
                else if (t.Namespace != "System" && !t.Namespace.StartsWith("Microsoft.Data.Spatial") && !t.Namespace.StartsWith("Microsoft.OData.Edm.Library"))
                {
                    if (t.IsEnum == true)
                    {
                        return(new ODataEnumValue(value.ToString(), t.FullName));
                    }
                    else
                    {
                        // Build a complex type property. We consider type t to be primitive if t.Namespace is  "System" or if t is spatial type.
                        List <ODataProperty> properties     = new List <ODataProperty>();
                        IEdmStructuredType   structuredType = (IEdmStructuredType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, value);
                        foreach (var p in GetProperties(value, structuredType))
                        {
                            if (t.GetProperty(p.Name) != null)
                            {
                                properties.Add(p);
                            }
                            else if (structuredType.IsOpen)
                            {
                                var instance = value as OpenClrObject;
                                properties.Add(CreateODataProperty(instance.OpenProperties[p.Name], p.Name));
                            }
                        }

                        var complexValue = new ODataComplexValue()
                        {
                            TypeName = t.FullName, Properties = properties,
                        };

                        // Add Annotation in complex level
                        if (((ClrObject)value).Annotations != null)
                        {
                            foreach (InstanceAnnotationType annotation in ((ClrObject)value).Annotations)
                            {
                                if (string.IsNullOrEmpty(annotation.Target))
                                {
                                    complexValue.InstanceAnnotations.Add(new ODataInstanceAnnotation(annotation.Name, annotation.ConvertValueToODataValue()));
                                }
                            }
                        }
                        return(complexValue);
                    }
                }
            }
            return(value);
        }