/// <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); }
public static object CreateResource(IEdmType type) { var targetType = EdmClrTypeUtils.GetInstanceType(type.FullTypeName()); return(QuickCreateInstance(targetType)); }
/// <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); } }
/// <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); } }
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); } }
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); }
/// <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); }
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); }