/// <summary>
        /// Tries to read element from XML.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns>True if element was read.</returns>
        internal override bool TryReadElementFromXml(EwsServiceXmlReader reader)
        {
            switch (reader.LocalName)
            {
            case XmlElementNames.ExtendedFieldURI:
                this.propertyDefinition = new ExtendedPropertyDefinition();
                this.propertyDefinition.LoadFromXml(reader);
                return(true);

            case XmlElementNames.Value:
                EwsUtilities.Assert(
                    this.PropertyDefinition != null,
                    "ExtendedProperty.TryReadElementFromXml",
                    "PropertyDefintion is missing");

                string stringValue = reader.ReadElementValue();
                this.value = MapiTypeConverter.ConvertToValue(this.PropertyDefinition.MapiType, stringValue);
                return(true);

            case XmlElementNames.Values:
                EwsUtilities.Assert(
                    this.PropertyDefinition != null,
                    "ExtendedProperty.TryReadElementFromXml",
                    "PropertyDefintion is missing");

                StringList stringList = new StringList(XmlElementNames.Value);
                stringList.LoadFromXml(reader, reader.LocalName);
                this.value = MapiTypeConverter.ConvertToValue(this.PropertyDefinition.MapiType, stringList);
                return(true);

            default:
                return(false);
            }
        }
        /// <summary>
        /// Gets the string value.
        /// </summary>
        /// <returns>Value as string.</returns>
        private string GetStringValue()
        {
            if (MapiTypeConverter.IsArrayType(this.PropertyDefinition.MapiType))
            {
                Array array = this.Value as Array;
                if (array == null)
                {
                    return(string.Empty);
                }
                else
                {
                    StringBuilder sb = new StringBuilder();
                    sb.Append("[");
                    for (int index = array.GetLowerBound(0); index <= array.GetUpperBound(0); index++)
                    {
                        sb.Append(
                            MapiTypeConverter.ConvertToString(
                                this.PropertyDefinition.MapiType,
                                array.GetValue(index)));
                        sb.Append(",");
                    }
                    sb.Append("]");

                    return(sb.ToString());
                }
            }
            else
            {
                return(MapiTypeConverter.ConvertToString(this.PropertyDefinition.MapiType, this.Value));
            }
        }
        /// <summary>
        /// Serializes the property to a Json value.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <returns>
        /// A Json value (either a JsonObject, an array of Json values, or a Json primitive)
        /// </returns>
        internal override object InternalToJson(ExchangeService service)
        {
            JsonObject jsonExtendedProp = new JsonObject();

            JsonObject jsonExtendedFieldUri = new JsonObject();

            this.PropertyDefinition.AddJsonProperties(jsonExtendedFieldUri, service);

            jsonExtendedProp.Add(XmlElementNames.ExtendedFieldURI, jsonExtendedFieldUri);

            if (MapiTypeConverter.IsArrayType(this.PropertyDefinition.MapiType))
            {
                List <object> values = new List <object>();

                foreach (object value in this.Value as Array)
                {
                    values.Add(MapiTypeConverter.ConvertToString(this.PropertyDefinition.MapiType, value));
                }

                jsonExtendedProp.Add(XmlElementNames.Values, values.ToArray());
            }
            else
            {
                jsonExtendedProp.Add(
                    XmlElementNames.Value,
                    MapiTypeConverter.ConvertToString(this.PropertyDefinition.MapiType, this.Value));
            }

            return(jsonExtendedProp);
        }
        /// <summary>
        /// Writes elements to XML.
        /// </summary>
        /// <param name="writer">The writer.</param>
        internal override void WriteElementsToXml(EwsServiceXmlWriter writer)
        {
            this.PropertyDefinition.WriteToXml(writer);

            if (MapiTypeConverter.IsArrayType(this.PropertyDefinition.MapiType))
            {
                Array array = this.Value as Array;
                writer.WriteStartElement(XmlNamespace.Types, XmlElementNames.Values);
                for (int index = array.GetLowerBound(0); index <= array.GetUpperBound(0); index++)
                {
                    writer.WriteElementValue(
                        XmlNamespace.Types,
                        XmlElementNames.Value,
                        MapiTypeConverter.ConvertToString(this.PropertyDefinition.MapiType, array.GetValue(index)));
                }
                writer.WriteEndElement();
            }
            else
            {
                writer.WriteElementValue(
                    XmlNamespace.Types,
                    XmlElementNames.Value,
                    MapiTypeConverter.ConvertToString(this.PropertyDefinition.MapiType, this.Value));
            }
        }
        /// <summary>
        /// Tries to get property value.
        /// </summary>
        /// <param name="propertyDefinition">The property definition.</param>
        /// <param name="propertyValue">The property value.</param>
        /// <typeparam name="T">Type of expected property value.</typeparam>
        /// <returns>True if property exists in collection.</returns>
        internal bool TryGetValue <T>(ExtendedPropertyDefinition propertyDefinition, out T propertyValue)
        {
            ExtendedProperty extendedProperty;

            if (this.TryGetProperty(propertyDefinition, out extendedProperty))
            {
                // Verify that the type parameter and property definition's type are compatible.
                var targetType = typeof(T);
                if (MapiTypeConverter.IsArrayType(propertyDefinition.MapiType) && typeof(T).IsArray)
                {
                    targetType = typeof(T).GetElementType();
                }
                if (!targetType.IsAssignableFrom(propertyDefinition.Type))
                {
                    string errorMessage = string.Format(
                        Strings.PropertyDefinitionTypeMismatch,
                        EwsUtilities.GetPrintableTypeName(propertyDefinition.Type),
                        EwsUtilities.GetPrintableTypeName(typeof(T)));
                    throw new ArgumentException(errorMessage, "propertyDefinition");
                }

                propertyValue = (T)extendedProperty.Value;
                return(true);
            }
            else
            {
                propertyValue = default(T);
                return(false);
            }
        }
        /// <summary>
        /// Loads from json.
        /// </summary>
        /// <param name="jsonProperty">The json property.</param>
        /// <param name="service">The service.</param>
        internal override void LoadFromJson(JsonObject jsonProperty, ExchangeService service)
        {
            foreach (string key in jsonProperty.Keys)
            {
                switch (key)
                {
                case XmlElementNames.ExtendedFieldURI:
                    this.propertyDefinition = new ExtendedPropertyDefinition();
                    this.propertyDefinition.LoadFromJson(jsonProperty.ReadAsJsonObject(key));
                    break;

                case XmlElementNames.Value:
                    EwsUtilities.Assert(
                        this.PropertyDefinition != null,
                        "ExtendedProperty.TryReadElementFromXml",
                        "PropertyDefintion is missing");

                    string stringValue = jsonProperty.ReadAsString(key);
                    this.value = MapiTypeConverter.ConvertToValue(this.PropertyDefinition.MapiType, stringValue);
                    break;

                case XmlElementNames.Values:
                    EwsUtilities.Assert(
                        this.PropertyDefinition != null,
                        "ExtendedProperty.TryReadElementFromXml",
                        "PropertyDefintion is missing");

                    StringList stringList = new StringList(XmlElementNames.Value);
                    ((IJsonCollectionDeserializer)stringList).CreateFromJsonCollection(jsonProperty.ReadAsArray(key), service);
                    this.value = MapiTypeConverter.ConvertToValue(this.PropertyDefinition.MapiType, stringList);
                    break;

                default:
                    break;
                }
            }
        }