/*
         * Converts an object to an XML element string.
         */
        public static string ConvertToElement(string name, object objectToConvert, XMLVersion version)
        {
            // Return a serialized XML element if it is an XML element.
            if (objectToConvert is VersionedXMLElement)
            {
                return(((VersionedXMLElement)objectToConvert).Serialize(version, name));
            }

            // Return the object as a string.
            return("<" + name + ">" + ConvertToString(objectToConvert, version) + "</" + name + ">");
        }
        /*
         * Converts a string to an object.
         */
        public static object DeserializeToObject(string value, Type propertyType, XMLVersion version)
        {
            // Get the underlying type if it is nullable.
            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                propertyType = propertyType.GetGenericArguments()[0];
            }

            // Return an enum if a name matches.
            if (propertyType.IsEnum)
            {
                // Return if an attribute matches.
                foreach (var enumItem in Enum.GetValues(propertyType))
                {
                    foreach (XMLEnum attribute in propertyType.GetField(enumItem.ToString()).GetCustomAttributes(typeof(XMLEnum), false))
                    {
                        if (attribute.IsVersionValid(version) && attribute.Name == value)
                        {
                            return(enumItem);
                        }
                    }
                }

                // Return if a name matches.
                foreach (var enumItem in Enum.GetValues(propertyType))
                {
                    if (enumItem.ToString() == value && propertyType.GetField(enumItem.ToString()).GetCustomAttributes(typeof(XMLEnum), false).Length == 0)
                    {
                        return(enumItem);
                    }
                }

                // Throw an exception.
                throw new InvalidVersionException(propertyType.Name + "." + value, version);
            }

            // Return a converted string.
            var typeConverter = TypeDescriptor.GetConverter(propertyType);

            return(typeConverter.ConvertFromString(value));
        }
        /*
         * Serializes the element.
         */
        public string Serialize(XMLVersion version)
        {
            // Get the name.
            string name             = null;
            bool   attributeDefined = false;
            var    selfType         = this.GetType();

            foreach (XMLElement attribute in selfType.GetCustomAttributes(typeof(XMLElement), true))
            {
                attributeDefined = true;
                if (attribute.IsVersionValid(version))
                {
                    if (name == null)
                    {
                        // Set the name if it is null.
                        name = attribute.Name;
                    }
                    else
                    {
                        // Throw an exception if overlapping names exist (could cause unexpected behavior).
                        throw new OverlappingVersionsException(selfType.Name, version);
                    }
                }
            }

            // Throw an exception if an attribute is defined but the name isn't. This happens
            // when the serializing version is invalid.
            if (name == null && attributeDefined)
            {
                throw new InvalidVersionException(selfType.Name, version);
            }

            // Set the name to the object name if no attribute is present.
            if (name == null)
            {
                name = selfType.Name;
            }

            // Serialize the object.
            return(this.Serialize(version, name));
        }
        /*
         * Returns if a version is valid.
         */
        public bool IsVersionValid(XMLVersion otherVersion)
        {
            // Create the versions to compare. If they are null, the versions will be null.
            var firstVersion   = XMLVersion.FromString(this.FirstVersion);
            var removedVersion = XMLVersion.FromString(this.RemovedVersion);

            // Return if the version is valid.
            if (firstVersion != null && removedVersion != null)
            {
                return(firstVersion <= otherVersion && removedVersion > otherVersion);
            }
            else if (firstVersion != null)
            {
                return(firstVersion <= otherVersion);
            }
            else if (removedVersion != null)
            {
                return(removedVersion > otherVersion);
            }

            // Return true (first and removed versions not defined).
            return(true);
        }
        /*
         * Converts an XML element to an object.
         */
        public static object DeserializeToObject(XElement xmlElement, Type propertyType, XMLVersion version)
        {
            // Return a parsed XML element.
            if (IsOfType(propertyType, typeof(VersionedXMLElement)))
            {
                if (xmlElement.Value != "" || xmlElement.FirstAttribute != null)
                {
                    return(DeserializeType(xmlElement.ToString(), version, propertyType));
                }
                else
                {
                    return(null);
                }
            }

            // Return a converted string.
            return(DeserializeToObject(xmlElement.Value, propertyType, version));
        }
 /*
  * Deserializes a string to an XML element.
  */
 public static T Deserialize <T>(string xmlString, XMLVersion version)
 {
     return((T)DeserializeType(xmlString, version, typeof(T)));
 }
        /*
         * Deserializes an object.
         */
        public static object DeserializeType(string xmlString, XMLVersion version, Type type)
        {
            xmlString = xmlString.Trim();

            // Create the new object.
            var newObject = Convert.ChangeType(Activator.CreateInstance(type, new object[] { }), type);
            var selfType  = newObject.GetType();
            var members   = selfType.GetMembers();

            // Create an XML parser and get the attributes and elements.
            var xmlDocument = XDocument.Parse(xmlString);
            var elements    = xmlDocument.Root.Elements().ToArray();
            var attributes  = xmlDocument.Root.Attributes().ToArray();

            // Set the attributes.
            foreach (var xmlAttribute in attributes)
            {
                // Find the attribute to add to.
                MemberInfo memberToSet = null;
                foreach (var member in members)
                {
                    foreach (XMLAttribute attribute in member.GetCustomAttributes(typeof(XMLAttribute), true))
                    {
                        var property = selfType.GetProperty(member.Name);
                        if (property != null)
                        {
                            if (attribute.IsVersionValid(version) &&
                                attribute.Name.ToLower() == xmlAttribute.Name.LocalName.ToLower())
                            {
                                if (memberToSet != null)
                                {
                                    // Throw an exception if the attribute overlaps.
                                    throw new OverlappingVersionsException(member.Name, version);
                                }
                                else
                                {
                                    memberToSet = member;
                                }
                            }
                        }
                        else
                        {
                            // Throw an exception if the property is null ("{ get; set; }" is missing).
                            throw new MissingGetterException(member.Name);
                        }
                    }
                }

                // If the attribute exists, set the value.
                if (memberToSet != null)
                {
                    var property           = selfType.GetProperty(memberToSet.Name);
                    var deserializedObject = DeserializeToObject(xmlAttribute.Value, property.PropertyType, version);
                    property.SetValue(newObject, deserializedObject);
                }
            }

            // Set the elements.
            var unknownElements = new List <string>();

            foreach (var xmlElement in elements)
            {
                // Find the attribute to add to.
                MemberInfo memberToSet = null;
                foreach (var member in members)
                {
                    foreach (XMLElement attribute in member.GetCustomAttributes(typeof(XMLElement), true))
                    {
                        var property = selfType.GetProperty(member.Name);
                        if (property != null)
                        {
                            if (attribute.IsVersionValid(version) &&
                                attribute.Name.ToLower() == xmlElement.Name.LocalName.ToLower())
                            {
                                if (memberToSet != null)
                                {
                                    // Throw an exception if the attribute overlaps.
                                    throw new OverlappingVersionsException(member.Name, version);
                                }
                                else
                                {
                                    memberToSet = member;
                                }
                            }
                        }
                        else
                        {
                            // Throw an exception if the property is null ("{ get; set; }" is missing).
                            throw new MissingGetterException(member.Name);
                        }
                    }
                }

                // If the attribute exists, set the value.
                if (memberToSet != null)
                {
                    // Set the value.
                    var property     = selfType.GetProperty(memberToSet.Name);
                    var propertyType = property.PropertyType;
                    if (IsOfType(propertyType, typeof(IList)))
                    {
                        var deserializedObject = DeserializeToObject(xmlElement, propertyType.GetGenericArguments()[0], version);
                        ((IList)property.GetValue(newObject)).Add(deserializedObject);
                    }
                    else
                    {
                        var deserializedObject = DeserializeToObject(xmlElement, propertyType, version);
                        property.SetValue(newObject, deserializedObject);
                    }
                }
                else
                {
                    unknownElements.Add(xmlElement.ToString());
                }
            }

            // Parse unknown elements.
            var method = type.GetMethod("ParseAdditionalElements");

            if (method != null)
            {
                method.Invoke(newObject, new object[2] {
                    version, unknownElements
                });
            }

            // Return the new object.
            return(newObject);
        }
Ejemplo n.º 8
0
 public InvalidVersionException(string name, XMLVersion version) : base(name + " can't be used for version " + version.MainVersion + "." + version.SubVersion + ".")
 {
 }
Ejemplo n.º 9
0
 public OverlappingVersionsException(string name, XMLVersion version) : base(name + " has overlapping version information for version " + version.MainVersion + "." + version.SubVersion + ". This makes the serialization ambiguous.")
 {
 }
 /*
  * Parses elements that aren't defined by properties.
  */
 public virtual void ParseAdditionalElements(XMLVersion version, List <string> elements)
 {
 }
 /*
  * Returns additional elements to add when serializing.
  * This method must handle all escaping of special characters.
  */
 public virtual List <string> GetAdditionalElements(XMLVersion version)
 {
     return(this.additionalElements);
 }
 /*
  * Invoked before serializing the object to finalize
  * setting of elements.
  */
 public virtual void PreSerialize(XMLVersion version)
 {
 }
        /*
         * Converts an object to a string.
         */
        public static string ConvertToString(object objectToConvert, XMLVersion version)
        {
            // Return an XML string if it is an XML object.
            if (objectToConvert is VersionedXMLElement)
            {
                return(((VersionedXMLElement)objectToConvert).Serialize(version));
            }

            // Return an XSD time if it is a DateTime.
            if (objectToConvert is DateTime)
            {
                // Get the components.
                var dateTime = (DateTime)objectToConvert;
                var year     = dateTime.Year.ToString();
                var month    = dateTime.Month.ToString();
                var day      = dateTime.Day.ToString();

                // Add the leading zeros.
                if (dateTime.Month < 10)
                {
                    month = "0" + month;
                }
                if (dateTime.Day < 10)
                {
                    day = "0" + day;
                }

                // Return the formatted time.
                return(year + "-" + month + "-" + day);
            }

            // Return a boolean as lowercase if it is a bool.
            if (objectToConvert is bool)
            {
                return(objectToConvert.ToString().ToLower());
            }

            // Return an enum value if it is an enum.
            if (objectToConvert.GetType().IsEnum)
            {
                // Get the name of the enum.
                var enumType         = objectToConvert.GetType();
                var enumName         = Enum.GetName(enumType, objectToConvert);
                var attributeDefined = false;
                var nameDefined      = false;
                foreach (XMLEnum attribute in enumType.GetField(enumName).GetCustomAttributes(typeof(XMLEnum), false))
                {
                    attributeDefined = true;
                    if (attribute.IsVersionValid(version))
                    {
                        if (nameDefined == false)
                        {
                            // Set the name if it is null.
                            nameDefined = true;
                            enumName    = attribute.Name;
                        }
                        else
                        {
                            // Throw an exception if overlapping names exist (could cause unexpected behavior).
                            throw new OverlappingVersionsException(enumType.Name + "." + Enum.GetName(enumType, objectToConvert), version);
                        }
                    }
                }

                // Throw an exception if the attribute is defined but not set.
                if (attributeDefined && !nameDefined)
                {
                    throw new InvalidVersionException(objectToConvert.GetType().Name + "." + enumName, version);
                }

                // Return the escaped enum value.
                return(SecurityElement.Escape(enumName));
            }

            // Return the ToString result.
            return(SecurityElement.Escape(objectToConvert.ToString()));
        }
        /*
         * Serializes the element with a give name.
         */
        public string Serialize(XMLVersion version, string elementName)
        {
            var selfType  = this.GetType();
            var members   = selfType.GetMembers();
            var xmlString = "<" + elementName;

            // Pre-serialize the object.
            this.PreSerialize(version);

            // Add the attributes.
            foreach (var member in members)
            {
                bool attributeAdded = false;
                foreach (XMLAttribute attribute in member.GetCustomAttributes(typeof(XMLAttribute), true))
                {
                    var property = selfType.GetProperty(member.Name);
                    if (property != null)
                    {
                        if (attribute.IsVersionValid(version))
                        {
                            if (attributeAdded)
                            {
                                // Throw an exception if the attribute overlaps.
                                throw new OverlappingVersionsException(member.Name, version);
                            }
                            else
                            {
                                // Add the attribute if it isn't null.
                                attributeAdded = true;
                                var value = property.GetValue(this, null);
                                if (value != null)
                                {
                                    // Add the attribute.
                                    xmlString += " " + attribute.Name + "=\"" + ConvertToString(value, version) + "\"";
                                }
                            }
                        }
                    }
                    else
                    {
                        // Throw an exception if the property is null ("{ get; set; }" is missing).
                        throw new MissingGetterException(member.Name);
                    }
                }
            }

            // Add the additional attributes.
            foreach (var attributeName in this.additionalAttributes.Keys)
            {
                xmlString += " " + attributeName + "=\"" + this.additionalAttributes[attributeName] + "\"";
            }
            xmlString += ">";

            // Add the child elements.
            foreach (var member in members)
            {
                bool elementAdded = false;
                foreach (XMLElement attribute in member.GetCustomAttributes(typeof(XMLElement), true))
                {
                    var property = selfType.GetProperty(member.Name);
                    if (property != null)
                    {
                        var value = property.GetValue(this, null);
                        if (value != null)
                        {
                            if (attribute.IsVersionValid(version))
                            {
                                if (elementAdded)
                                {
                                    // Throw an exception if the element overlaps.
                                    throw new OverlappingVersionsException(member.Name, version);
                                }
                                else
                                {
                                    // Add the child element.
                                    elementAdded = true;
                                    if (value is IList)
                                    {
                                        foreach (var listObject in (IList)value)
                                        {
                                            xmlString += ConvertToElement(attribute.Name, listObject, version);
                                        }
                                    }
                                    else
                                    {
                                        xmlString += ConvertToElement(attribute.Name, value, version);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // Throw an exception if the property is null ("{ get; set; }" is missing).
                        throw new MissingGetterException(member.Name);
                    }
                }
            }

            // Add additional child elements.
            var additionalElements = this.GetAdditionalElements(version);

            if (additionalElements != null)
            {
                foreach (var additionalElement in additionalElements)
                {
                    xmlString += additionalElement;
                }
            }

            // Return the final string with the ending tag.
            return(xmlString + "</" + elementName + ">");
        }