/// <summary>
        /// Reads the variable definition.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <returns></returns>
        /// <exception cref="XacmlSerializationException">Wrong VariableDefinition element content</exception>
        protected virtual XacmlVariableDefinition ReadVariableDefinition(XmlReader reader) {
            Contract.Requires<ArgumentNullException>(reader != null, "reader");
            Contract.Requires<XmlException>(reader.IsStartElement(XacmlConstants.ElementNames.VariableDefinition, this.version.NamespacePolicy));

            string variableId = this.ReadAttribute<string>(reader, XacmlConstants.AttributeNames.VariableId);

            XacmlVariableDefinition result = new XacmlVariableDefinition(variableId);
            if (reader.IsEmptyElement) {
                return result;
            }

            reader.ReadStartElement(XacmlConstants.ElementNames.VariableDefinition, this.version.NamespacePolicy);

            switch (reader.Name) {
                case XacmlConstants.ElementNames.VariableReference: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.VariableReference, this.version.NamespacePolicy,
                            new ReadElement<XacmlVariableReference>(
                                o => new XacmlVariableReference(this.ReadAttribute<string>(reader, XacmlConstants.AttributeNames.VariableId))
                            ), reader);
                        break;
                    }
                case XacmlConstants.ElementNames.AttributeSelector: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.AttributeSelector, this.version.NamespacePolicy, this.ReadAttributeSelector, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.ResourceAttributeDesignator: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.ResourceAttributeDesignator, this.version.NamespacePolicy, this.ReadAttributeDesignator, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.ActionAttributeDesignator: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.ActionAttributeDesignator, this.version.NamespacePolicy, this.ReadAttributeDesignator, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.EnvironmentAttributeDesignator: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.EnvironmentAttributeDesignator, this.version.NamespacePolicy, this.ReadAttributeDesignator, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.SubjectAttributeDesignator: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.SubjectAttributeDesignator, this.version.NamespacePolicy, this.ReadAttributeDesignator, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.AttributeValue: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.AttributeValue, this.version.NamespacePolicy, this.ReadAttributeValue, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.Function: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.Function, this.version.NamespacePolicy, this.ReadFunction, reader);
                        break;
                    }
                case XacmlConstants.ElementNames.Apply: {
                        result.Property = this.ReadOptional(XacmlConstants.ElementNames.Apply, this.version.NamespacePolicy, this.ReadApply, reader);
                        break;
                    }
                default: {
                        throw Diagnostic.DiagnosticTools.ExceptionUtil.ThrowHelperError(new XacmlSerializationException("Wrong VariableDefinition element content"));
                    }
            }

            reader.ReadEndElement();

            return result;
        }
        /// <summary>
        /// Writes the variable definition.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <param name="variableDefinition">The variable definition.</param>
        protected virtual void WriteVariableDefinition(XmlWriter writer, XacmlVariableDefinition variableDefinition) {
            writer.WriteStartElement(XacmlConstants.Prefixes.Policy, XacmlConstants.ElementNames.VariableDefinition, this.version.NamespacePolicy);
            writer.WriteAttributeString(XacmlConstants.AttributeNames.VariableId, variableDefinition.VariableId);

            this.WriteExpressionType(writer, variableDefinition);

            writer.WriteEndElement();
        }