/// <summary>Reads a typed property from the specified XmlReader.</summary> /// <param name='reader'>XmlReader to read from.</param> /// <param name='propertyName'>Name of property to read.</param> /// <param name='resourceProperty'>resourceProperty whose value is to be read.</param> /// <returns>The instance read, possibly null.</returns> private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceProperty resourceProperty) { Debug.Assert(reader != null, "reader != null"); Debug.Assert(propertyName != null, "propertyName != null"); ResourceType propertyType = null; // If this is a open property OR we do not have to do type conversion for primitive types, // read the type from the payload. bool readTypeFromWire = resourceProperty == null || (!this.Service.Configuration.EnableTypeConversion && resourceProperty.ResourceType.ResourceTypeKind == ResourceTypeKind.Primitive); if (readTypeFromWire) { propertyType = this.ReadOpenPropertyTypeAttribute(reader); } else { propertyType = resourceProperty.ResourceType; } if (this.propertiesApplied != null) { this.propertiesApplied.AddPropertyToTypeMapItem( this.BuildPropertyPath(propertyName), propertyType.FullName); } object propertyValue; String appliedPropertyName = resourceProperty != null ? resourceProperty.Name : propertyName; switch (propertyType.ResourceTypeKind) { case ResourceTypeKind.ComplexType: this.CheckAndIncrementObjectCount(); bool isNull = HasNullAttributeWithTrueValue(reader); if (this.propertiesApplied != null) { this.propertiesApplied.AddAppliedProperty(this.BuildPropertyPath(appliedPropertyName), isNull); } if (isNull) { propertyValue = null; } else { propertyValue = this.Updatable.CreateResource(null, propertyType.FullName); if (!reader.IsEmptyElement) { // Step inside the complex type, apply its properties, and pop back out. using (XmlReader propertyReader = reader.ReadSubtree()) { if (!WebUtil.XmlReaderEnsureElement(propertyReader)) { throw DataServiceException.CreateBadRequestError( Strings.PlainXml_PropertyLacksElement(propertyName)); } propertyReader.ReadStartElement(); String savedPath = this.currentPathPrefix; this.currentPathPrefix = String.IsNullOrEmpty(this.currentPathPrefix) ? appliedPropertyName : this.currentPathPrefix + "/" + appliedPropertyName; ApplyContent(propertyReader, propertyType, propertyValue); this.currentPathPrefix = savedPath; } Debug.Assert( reader.NodeType == XmlNodeType.EndElement, "reader.NodeType == XmlNodeType.EndElement -- otherwise ReadSubtree left outer read in incorrect position."); } } break; case ResourceTypeKind.EntityType: throw DataServiceException.CreateBadRequestError( Strings.PlainXml_NavigationPropertyNotSupported(propertyName)); default: Debug.Assert( propertyType.ResourceTypeKind == ResourceTypeKind.Primitive, "property.TypeKind == ResourceTypeKind.Primitive -- metadata shouldn't return " + propertyType.ResourceTypeKind); propertyValue = ReadElementString(reader, propertyName); // We need to convert the type to the wire type. Conversion to the property type happens in Deserializer.SetValue method. if (readTypeFromWire) { propertyValue = PlainXmlDeserializer.ConvertValuesForXml(propertyValue, propertyName, propertyType.InstanceType); } if (this.propertiesApplied != null) { this.propertiesApplied.AddAppliedProperty(this.BuildPropertyPath(appliedPropertyName), false); } break; } return(propertyValue); }