/// <summary>
        /// Writes the &lt;saml:ProxyRestriction> element.
        /// </summary>
        /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2ProxyRestriction"/>.</param>
        /// <param name="data">The <see cref="Saml2ProxyRestriction"/> to serialize.</param>
        protected virtual void WriteProxyRestriction(XmlWriter writer, Saml2ProxyRestriction data)
        {
            if (null == writer)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

            if (null == data)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data");
            }

            writer.WriteStartElement(Saml2Constants.Elements.ProxyRestricton, Saml2Constants.Namespace);

            // @Count - optional
            if (null != data.Count)
            {
                writer.WriteAttributeString(Saml2Constants.Attributes.Count, XmlConvert.ToString(data.Count.Value));
            }

            // <Audience> - 0-OO
            foreach (Uri uri in data.Audiences)
            {
                writer.WriteElementString(Saml2Constants.Elements.Audience, uri.AbsoluteUri);
            }

            writer.WriteEndElement();
        }
        /// <summary>
        /// Reads the &lt;saml:ProxyRestriction> element, or a &lt;saml:Condition>
        /// element that specifies an xsi:type of saml:ProxyRestrictionType.
        /// </summary>
        /// <remarks>
        /// In the default implementation, the maximum value of the Count attribute 
        /// is limited to Int32.MaxValue.
        /// </remarks>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2ProxyRestriction"/> element.</param>
        /// <returns>An instance of <see cref="Saml2ProxyRestriction"/></returns>
        protected virtual Saml2ProxyRestriction ReadProxyRestriction(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            // throw if wrong element
            bool isConditionElement = false;
            if (reader.IsStartElement(Saml2Constants.Elements.Condition, Saml2Constants.Namespace))
            {
                isConditionElement = true;
            }
            else if (!reader.IsStartElement(Saml2Constants.Elements.ProxyRestricton, Saml2Constants.Namespace))
            {
                reader.ReadStartElement(Saml2Constants.Elements.ProxyRestricton, Saml2Constants.Namespace);
            }

            try
            {
                Saml2ProxyRestriction proxyRestriction = new Saml2ProxyRestriction();

                bool isEmpty = reader.IsEmptyElement;

                // @attributes
                string value;

                // @xsi:type -- if we're a <Condition> element, this declaration must be present
                XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.ProxyRestrictionType, Saml2Constants.Namespace, isConditionElement);

                // @Count - optional
                value = reader.GetAttribute(Saml2Constants.Attributes.Count);
                if (!string.IsNullOrEmpty(value))
                {
                    proxyRestriction.Count = XmlConvert.ToInt32(value);
                }

                // content
                reader.Read();
                if (!isEmpty)
                {
                    // <Audience> - 0-OO
                    while (reader.IsStartElement(Saml2Constants.Elements.Audience, Saml2Constants.Namespace))
                    {
                        proxyRestriction.Audiences.Add(ReadSimpleUriElement(reader));
                    }

                    reader.ReadEndElement();
                }

                return proxyRestriction;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(reader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }