示例#1
0
        /// <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);
        }