/// <summary> /// Handle $expand /// </summary> /// <param name="entry">Entry</param> /// <param name="edmParent">Parent EntitySet</param> /// <param name="targetVersion">Target Version</param> /// <param name="expandedNavigationItems">Expand Items</param> /// <param name="parentId">Parent Id</param> private void GenerateDeltaItemsFromExpand(object entry, IEdmNavigationSource edmParent, ODataVersion targetVersion, IEnumerable <ExpandedNavigationSelectItem> expandedNavigationItems, string parentId) { foreach (var navigationProperty in ((IEdmEntityType)EdmClrTypeUtils.GetEdmType(this.DataSource.Model, entry)).NavigationProperties()) { var expandedNavigationItem = GetExpandedNavigationItem(expandedNavigationItems, navigationProperty.Name); if (expandedNavigationItem != null) { bool isCollection = navigationProperty.Type.IsCollection(); ExpandSelectItemHandler expandItemHandler = new ExpandSelectItemHandler(entry); expandedNavigationItem.HandleWith(expandItemHandler); var propertyValue = expandItemHandler.ExpandedChildElement; if (propertyValue != null) { IEdmNavigationSource targetSource = edmParent.FindNavigationTarget(navigationProperty); if (isCollection) { var expandedEntities = propertyValue as IEnumerable; foreach (var expandedEntity in expandedEntities) { GenerateDeltaItemFromEntry(expandedEntity, targetSource, targetVersion, expandedNavigationItem.SelectAndExpand, parentId, navigationProperty.Name); } } else { GenerateDeltaItemFromEntry(propertyValue, targetSource, targetVersion, expandedNavigationItem.SelectAndExpand, parentId, navigationProperty.Name); } } // Handle deleted entry and link here GenerateDeltaItemsFromDeletedEntities(parentId, navigationProperty.Name); } } }
private static void UpdateCore(object target, string propertyName, object propertyValue) { var odataComplexValue = propertyValue as ODataComplexValue; var odataCollectionValue = propertyValue as ODataCollectionValue; var odataEnumValue = propertyValue as ODataEnumValue; var odataPrimitiveValue = propertyValue as ODataPrimitiveValue; if (odataComplexValue != null) { var property = target.GetType().GetProperty(propertyName); if (property != null) { var value = property.GetValue(target, null); if (value == null) { var valueType = EdmClrTypeUtils.GetInstanceType(odataComplexValue.TypeName); var propertyType = property.PropertyType; if (valueType.IsSubclassOf(propertyType) || valueType == propertyType) { value = Utility.QuickCreateInstance(valueType); } else { throw new InvalidOperationException(string.Format("{0} is not equal or derived from {1}", valueType, propertyType)); } property.SetValue(target, value, null); } foreach (var p in odataComplexValue.Properties) { UpdateCore(value, p.Name, p.Value); } return; } } else if (odataCollectionValue != null) { var property = target.GetType().GetProperty(propertyName); if (property != null) { var collection = Utility.QuickCreateInstance(property.PropertyType); foreach (var item in odataCollectionValue.Items) { var itemType = property.PropertyType.GetGenericArguments().Single(); odataComplexValue = item as ODataComplexValue; odataCollectionValue = item as ODataCollectionValue; object collectionItem = null; if (odataComplexValue != null) { // TODO: call Create method to new instance instead collectionItem = Utility.QuickCreateInstance(itemType); foreach (var p in odataComplexValue.Properties) { UpdateCore(collectionItem, p.Name, p.Value); } } else if (odataCollectionValue != null) { // TODO, check should support this type or not throw new NotImplementedException(); } else { collectionItem = ODataObjectModelConverter.ConvertPropertyValue(item, itemType); } property.PropertyType.GetMethod("Add").Invoke(collection, new object[] { collectionItem }); } property.SetValue(target, collection, null); return; } } else { var property = target.GetType().GetProperty(propertyName); if (property != null) { property.SetValue(target, ODataObjectModelConverter.ConvertPropertyValue(propertyValue, property.PropertyType), null); return; } } var openClrObject = target as OpenClrObject; if (openClrObject != null) { var structuredType = (IEdmStructuredType)EdmClrTypeUtils.GetEdmType(DataSourceManager.GetCurrentDataSource().Model, openClrObject); //check if the edmType is an open type if (structuredType.IsOpen) { if (odataCollectionValue != null) { // Collection of Edm.String if (odataCollectionValue.TypeName == "Collection(Edm.String)") { var collection = new Collection <string>(); foreach (var it in odataCollectionValue.Items) { collection.Add(it as string); } openClrObject.OpenProperties[propertyName] = collection; } else { // TODO: handle other types. throw new NotImplementedException(); } } else if (odataComplexValue != null) { var type = EdmClrTypeUtils.GetInstanceType(odataComplexValue.TypeName); var value = Utility.QuickCreateInstance(type); foreach (var property in odataComplexValue.Properties) { UpdateCore(value, property.Name, property.Value); } openClrObject.OpenProperties[propertyName] = value; } else if (odataEnumValue != null) { var type = EdmClrTypeUtils.GetInstanceType(odataEnumValue.TypeName); openClrObject.OpenProperties[propertyName] = ODataObjectModelConverter.ConvertPropertyValue(propertyValue, type); } else if (odataPrimitiveValue != null) { openClrObject.OpenProperties[propertyName] = odataPrimitiveValue.Value; } else { openClrObject.OpenProperties[propertyName] = propertyValue; } } } }