private MaterializeAtom ReadPropertyFromAtom(ClientPropertyAnnotation property) { DataServiceContext context = (DataServiceContext)this.Source; bool merging = context.ApplyingChanges; try { context.ApplyingChanges = true; // store the results so that they can be there in the response body. Type elementType = property.IsEntityCollection ? property.EntityCollectionItemType : property.NullablePropertyType; IList results = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType)); DataServiceQueryContinuation continuation = null; // elementType.ElementType has Nullable stripped away, use nestedType for materializer using (MaterializeAtom materializer = this.GetMaterializer(this.plan)) { Debug.Assert(materializer != null, "materializer != null -- otherwise GetMaterializer() returned null rather than empty"); #if ASTORIA_OPEN_OBJECT object openProperties = null; #endif // when SetLink to null, we cannot get materializer because have no-content response. if (materializer.IsNoContentResponse() && property.GetValue(entity) != null && context.MergeOption != MergeOption.AppendOnly && context.MergeOption != MergeOption.NoTracking) { property.SetValue(this.entity, null, propertyName, false); } else { foreach (object child in materializer) { if (property.IsEntityCollection) { results.Add(child); } else if (property.IsPrimitiveOrEnumOrComplexCollection) { Debug.Assert(property.PropertyType.IsAssignableFrom(child.GetType()), "Created instance for storing collection items has to be compatible with the actual one."); // Collection materialization rules requires to clear the collection if not null or set the property first and then add the collection items object collectionInstance = property.GetValue(this.entity); if (collectionInstance == null) { // type of child has been resolved as per rules for collections so it is the correct type to instantiate collectionInstance = Activator.CreateInstance(child.GetType()); // allowAdd is false - we need to assign instance as the new property value property.SetValue(this.entity, collectionInstance, this.propertyName, false /* allowAdd? */); } else { // Clear existing collection property.ClearBackingICollectionInstance(collectionInstance); } foreach (var collectionItem in (IEnumerable)child) { Debug.Assert(property.PrimitiveOrComplexCollectionItemType.IsAssignableFrom(collectionItem.GetType()), "Type of materialized collection items have to be compatible with the type of collection items in the actual collection property."); property.AddValueToBackingICollectionInstance(collectionInstance, collectionItem); } results.Add(collectionInstance); } else { #if ASTORIA_OPEN_OBJECT property.SetValue(this.entity, child, this.propertyName, ref openProperties, false); #else // it is either primitive type, complex type or 1..1 navigation property so we just allow setting the value but not adding. property.SetValue(this.entity, child, this.propertyName, false); results.Add(child); #endif } } } continuation = materializer.GetContinuation(null); } return(MaterializeAtom.CreateWrapper(context, results, continuation)); } finally { context.ApplyingChanges = merging; } }