Example #1
0
        private static void SerializeMembers(
            XDocument document,
            IXPathSerializable serializable,
            HashSet <object> objectsAlreadySerialized,
            SerializableMemberInfo[] membersToSerialize,
            MemberInfo[] useMembers      = null,
            Mapping parentMapping        = null,
            bool emitTypeInfo            = false,
            int version                  = 0,
            IFormatProvider provider     = null,
            XmlNamespaceManager resolver = null)
        {
            foreach (var member in membersToSerialize)
            {
                // Skip non-serializable members
                if (member.GetSingleCustomAttribute <NotForSerializationAttribute>() != null)
                {
                    continue;
                }

                // Check if the member is serializable in the current version
                int serializedFromVersion = 0;
                var versionAttribute      = member.GetSingleCustomAttribute <SerializedFromVersionAttribute>();
                if (versionAttribute != null)
                {
                    serializedFromVersion = versionAttribute.Version;
                }
                if (version < serializedFromVersion)
                {
                    continue;
                }

                var mapping = member.GetMapping(serializable.GetType(), parentMapping);

                object value = member.GetValue(serializable);

                // Remember the type in case we need to emit it into the Xml
                Type deserializeAs = null;
                if (value != null && emitTypeInfo)
                {
                    deserializeAs = value.GetType();
                }

                var context = new SerializationContext(serializable, member, mapping, useMembers, deserializeAs, emitTypeInfo, version, provider, resolver);

                // TODO: what if mandatory?
                if (value != null && value.GetType().IsArray&& !mapping.AsBase64)
                {
                    SerializeArrayMember(document, value, context, objectsAlreadySerialized);
                }
                else
                {
                    if (value != null && typeof(IXPathSerializable).IsAssignableFrom(value.GetType()))
                    {
                        SerializeXPathSerializableMember(document, value, context, objectsAlreadySerialized);
                    }
                    else
                    {
                        SerializeSimpleMember(document, value, context);
                    }
                }
            }
        }
Example #2
0
        private static void LoadMembersFromXml(
            XDocument document,
            IXPathSerializable serializable,
            SerializableMemberInfo[] membersToLoad,
            MemberInfo[] useMembers,
            Mapping parentMapping,
            int version,
            IFormatProvider provider,
            XmlNamespaceManager resolver)
        {
            foreach (var member in membersToLoad)
            {
                // Skip non-serializable members
                if (member.GetSingleCustomAttribute <NotForSerializationAttribute>() != null)
                {
                    continue;
                }

                // Check if the member is serializable in the current version
                int serializedFromVersion = 0;
                var versionAttribute      = member.GetSingleCustomAttribute <SerializedFromVersionAttribute>();
                if (versionAttribute != null)
                {
                    serializedFromVersion = versionAttribute.Version;
                }
                if (version < serializedFromVersion)
                {
                    continue;
                }

                var mapping = member.GetMapping(serializable.GetType(), parentMapping);

                var mappedElement = document.Root.XPathSelectElement(mapping.ElementXPath, resolver);

                bool mappedToAttributeWhichIsNotFound =
                    !String.IsNullOrWhiteSpace(mapping.AttributeName) &&
                    (mappedElement == null || mappedElement.Attribute(XPathHelper.ConvertToXName(mapping.AttributeName, resolver)) == null);

                // Ensure mandatory xml elements/attributes are present
                if (mapping.IsXmlMandatory)
                {
                    if (mappedElement == null)
                    {
                        throw new SerializationException(
                                  String.Format(
                                      "Cannot deserialize {0} '{1}', type '{2}'. Could not find the element with path '{3}'",
                                      member.MemeberTypeString,
                                      member.Name,
                                      serializable.GetType(),
                                      mapping.ElementXPath));
                    }
                    else if (mappedToAttributeWhichIsNotFound)
                    {
                        throw new SerializationException(
                                  String.Format(
                                      "Cannot deserialize {0} '{1}', type '{2}'. Could not find the attribute '{3}' of the element with path '{4}'",
                                      member.MemeberTypeString,
                                      member.Name,
                                      serializable.GetType(),
                                      mapping.AttributeName,
                                      mapping.ElementXPath));
                    }
                }

                // Short-circuit for nulls
                if (mappedElement == null || mappedToAttributeWhichIsNotFound)
                {
                    member.SetValue(serializable, null);
                    continue;
                }
                if (string.IsNullOrWhiteSpace(mapping.AttributeName))
                {
                    var isNullAttribute = mappedElement.Attribute(Constants.NullValueAttributeName);
                    if (isNullAttribute != null)
                    {
                        member.SetValue(serializable, null);
                        continue;
                    }
                }

                // Determine the type of the deserialized value
                Type emittedType = null;
                if (mappedElement != null && string.IsNullOrWhiteSpace(mapping.AttributeName))
                {
                    var typeAttribute = mappedElement.Attribute(Constants.TypeInfoAttributeName);
                    if (typeAttribute != null)
                    {
                        emittedType = Type.GetType(typeAttribute.Value);                         // TODO: handle all kind of exceptions
                    }
                }
                Type deserializeAs;
                if (emittedType != null)
                {
                    deserializeAs = emittedType;
                }
                else
                {
                    deserializeAs = member.MemberType;
                }

                var context = new SerializationContext(
                    serializable,
                    member,
                    mapping,
                    useMembers,
                    deserializeAs,
                    version: version,
                    formatProvider: provider,
                    resolver: resolver);

                if (deserializeAs.IsArray && !mapping.AsBase64)
                {
                    LoadArrayMemberFromXml(mappedElement, context);
                }
                else if (typeof(IXPathSerializable).IsAssignableFrom(deserializeAs))
                {
                    LoadXPathSerializableMemberFromXml(document, context);
                }
                else
                {
                    LoadSimpleMemberFromXml(mappedElement, context);
                }
            }
        }
Example #3
0
        private static XDocument ToXmlInternal(
            XDocument document,
            IXPathSerializable serializable,
            HashSet <object> objectsAlreadySerialized,
            MemberInfo[] useMembers,
            Mapping parentMapping,
            bool emitTypeInfo,
            int version,
            IFormatProvider provider,
            XmlNamespaceManager resolver)
        {
            // Take care of circular references
            if (objectsAlreadySerialized.Contains(serializable))
            {
                throw new SerializationException(
                          String.Format("A circular reference was detected while serializing an object of type '{0}'", serializable.GetType()));
            }
            else
            {
                objectsAlreadySerialized.Add(serializable);
            }

            if (document == null)
            {
                document = new XDocument();
            }

            // Initialize namespace resolver from class attributes
            if (resolver == null)
            {
                resolver = new XmlNamespaceManager(new NameTable());
            }
            var namespaceAttributes = serializable.GetType().GetCustomAttributes(typeof(NamespacePrefixAttribute), true);

            foreach (NamespacePrefixAttribute namespaceAttribute in namespaceAttributes)
            {
                resolver.AddNamespace(namespaceAttribute.Prefix, namespaceAttribute.Uri);
            }

            // Ensure minimal xml structure
            var minimalXmlAttributes = serializable.GetType().GetCustomAttributes(typeof(MinimalXmlStructureAttribute), true);

            if (minimalXmlAttributes != null)
            {
                foreach (MinimalXmlStructureAttribute minimalXmlAttribute in minimalXmlAttributes)
                {
                    string xPath = minimalXmlAttribute.ElementXPath;
                    if (String.IsNullOrWhiteSpace(xPath))
                    {
                        xPath = XmlConvert.EncodeName(serializable.GetType().Name);
                    }
                    XmlOperations.GetOrCreateElement(document, xPath, resolver);
                }
            }

            var typeInfo = SerializableTypeInfo.GetTypeInfo(serializable.GetType());

            var membersToSerialize = typeInfo.Members.Where(x => useMembers == null || useMembers.Length == 0 || useMembers.Contains(x.MemberInfo));

            SerializeMembers(
                document,
                serializable,
                objectsAlreadySerialized,
                membersToSerialize.ToArray(),
                useMembers,
                parentMapping,
                emitTypeInfo,
                version,
                provider,
                resolver);

            // Return resulting document
            return(document);
        }