/// <summary>Writes the value of a complex object.</summary> /// <param name="element">Element to write.</param> /// <param name="propertyName">name of the property whose value needs to be written</param> /// <param name="expectedType">expected type of the property</param> /// <param name="relativeUri">relative uri for the complex type element</param> /// <param name="content">Content to write to.</param> /// <param name="currentSourceRoot">Epm source sub-tree corresponding to <paramref name="element"/></param> private void WriteComplexObjectValue(object element, string propertyName, ResourceType expectedType, string relativeUri, DictionaryContent content, EpmSourcePathSegment currentSourceRoot) { Debug.Assert(!String.IsNullOrEmpty(propertyName), "!String.IsNullOrEmpty(propertyName)"); Debug.Assert(expectedType != null, "expectedType != null"); Debug.Assert(!String.IsNullOrEmpty(relativeUri), "!String.IsNullOrEmpty(relativeUri)"); Debug.Assert(expectedType.ResourceTypeKind == ResourceTypeKind.ComplexType, "Must be complex type"); Debug.Assert(content != null, "content != null"); // Non-value complex types may form a cycle. // PERF: we can keep a single element around and save the HashSet initialization // until we find a second complex type - this saves the allocation on trees // with shallow (single-level) complex types. Debug.Assert(!expectedType.IsMediaLinkEntry, "!expectedType.IsMediaLinkEntry"); DictionaryContent valueProperties = new DictionaryContent(expectedType.Properties.Count); Debug.Assert(!expectedType.InstanceType.IsValueType, "!expectedType.Type.IsValueType -- checked in the resource type constructor."); if (element == null) { content.AddNull(expectedType.FullName, propertyName); } else { if (this.AddToComplexTypeCollection(element)) { ResourceType resourceType = WebUtil.GetNonPrimitiveResourceType(this.Provider, element); this.WriteObjectProperties(null, element, resourceType, null, relativeUri, null, valueProperties, currentSourceRoot); if (!valueProperties.IsEmpty) { content.Add(propertyName, resourceType.FullName, valueProperties); } this.RemoveFromComplexTypeCollection(element); } else { throw new InvalidOperationException(Strings.Serializer_LoopsNotAllowedInComplexTypes(propertyName)); } } }
/// <summary>Adds the null valued properties to the content section of a syndication entry</summary> /// <param name="currentRoot">Current root node</param> /// <param name="currentContent">Current collection to which property is to be added</param> private void AddNullValuesToContent(EpmNullValuedPropertyNode currentRoot, DictionaryContent currentContent) { foreach (EpmNullValuedPropertyNode node in currentRoot.Children) { bool found; DictionaryContent c = currentContent.Lookup(node.Name, out found); Debug.Assert(node.ResourceType != null, "node.ResourceType != null"); switch (node.ResourceType.ResourceTypeKind) { case ResourceTypeKind.ComplexType: if (!found) { // If a complex property is not found in content, it is either not being projected // or all of its properties are mapped and all of them have KeepInContent=false Debug.Assert(c == null, "when look up not found, c should be null."); if (node.Element != null) { Debug.Assert(node.Children.Count > 0, "If the property represented by the current node is not null, there must be children nodes."); // The complex property is not null, but some of its descendant properties are null. // We need to serialize the type name of the complex property. c = new DictionaryContent(); currentContent.Add(node.Name, node.ResourceType.FullName, c); } else { Debug.Assert(node.Children.Count == 0, "If the property represented by the current node is not null, there must not be any children node."); // The complex property is null, we write out m:null='true'. currentContent.AddNull(node.ResourceType.FullName, node.Name); } } if (c != null) { // Only add the children properties if the complex property is not null. this.AddNullValuesToContent(node, c); } break; case ResourceTypeKind.Primitive: Debug.Assert(c == null, "DictionaryContent not expected for primitive properties."); Debug.Assert(node.Element == null, "node.Element == null"); if (!found) { currentContent.AddNull(node.ResourceType.FullName, node.Name); } // if found, use the value in currentContent, we don't need to do anything here. break; case ResourceTypeKind.EntityType: Debug.Assert(false, "We cannot map navigation properties with friendly feeds."); break; } } }
/// <summary>Writes a primitive value to the specified output.</summary> /// <param name="primitive">Primitive value to write.</param> /// <param name="propertyName">name of the property whose value needs to be written</param> /// <param name="expectedTypeName">Type name of the property</param> /// <param name="content">Content dictionary to which the value should be written.</param> internal static void WritePrimitiveValue(object primitive, string propertyName, string expectedTypeName, DictionaryContent content) { Debug.Assert(!String.IsNullOrEmpty(propertyName), "!String.IsNullOrEmpty(propertyName)"); Debug.Assert(expectedTypeName != null, "expectedTypeName != null"); if (primitive == null) { content.AddNull(expectedTypeName, propertyName); } else { string primitiveString = PlainXmlSerializer.PrimitiveToString(primitive); Debug.Assert(primitiveString != null, "primitiveString != null"); content.Add(propertyName, expectedTypeName, primitiveString); } }