Exemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of <c>SerializationContext</c> class.
        /// </summary>
        /// <param name="serializable">The object which is serialized/deserialized.</param>
        /// <param name="member">The member whose value is serialized/deserialized.</param>
        /// <param name="mapping">The mapping info for the member.</param>
        /// <param name="useMembers">The list of members to use.</param>
        /// <param name="deserializeAs">The type that the value should be deserialized into.</param>
        /// <param name="emitTypeInfo">Specifies whether the type info should be emitted when serializing the object.</param>
        /// <param name="version">The version of the object that should be used when serializing the object.</param>
        /// <param name="formatProvider">The format provider passed to the serializer.</param>
        /// <param name="resolver">The xml namespace resolver.</param>
        public SerializationContext(
            IXPathSerializable serializable,
            SerializableMemberInfo member,
            Mapping mapping,
            MemberInfo[] useMembers,
            Type deserializeAs             = null,
            bool emitTypeInfo              = false,
            int version                    = 0,
            IFormatProvider formatProvider = null,
            XmlNamespaceManager resolver   = null)
        {
            if (serializable == null)
            {
                throw new ArgumentNullException("serializable");
            }
            if (member == null)
            {
                throw new ArgumentNullException("member");
            }
            if (mapping == null)
            {
                throw new ArgumentNullException("mapping");
            }

            this.Serializable      = serializable;
            this.Member            = member;
            this.Mapping           = mapping;
            this.FormatProvider    = formatProvider;
            this.EmitTypeInfo      = emitTypeInfo;
            this.DeserializeAs     = deserializeAs;
            this.NamespaceResolver = resolver;
            this.UseMembers        = useMembers;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Serializes an object to xml.
 /// </summary>
 /// <param name="serializable">The object to serialize.</param>
 /// <param name="emitTypeInfo">Specifies whether the type info should be emitted when serializing the object.</param>
 /// <param name="version">The version of the object that should be used when serializing the object.</param>
 /// <param name="provider">An object that supplies culture-specific formatting information.</param>
 /// <returns>The xml string with the serialized object.</returns>
 /// <exception cref="SerializationException">Is thrown if the serialization cannot be performed.</exception>
 public static string ToXml(
     this IXPathSerializable serializable,
     bool emitTypeInfo        = false,
     int version              = 0,
     IFormatProvider provider = null)
 {
     return(ToXmlInternal(
                new XDocument(),
                serializable,
                objectsAlreadySerialized: new HashSet <object>(),
                useMembers: null,
                parentMapping: null,
                emitTypeInfo: emitTypeInfo,
                version: version,
                provider: provider,
                resolver: null).ToString());
 }
Exemplo n.º 3
0
        private static MemberInfo[] GetFilterMembers <TFilter>(IXPathSerializable serializable, MemberFilter <TFilter> filter)
        {
            var members = new List <MemberInfo>();

            if (filter == null)
            {
                return(members.ToArray());
            }

            foreach (var expression in filter)
            {
                MemberExpression propertyExpression;

                var unary = expression.Body as UnaryExpression;
                if (unary != null)
                {
                    // In this case the return type of the property was not object,
                    // so .Net wrapped the expression inside of a unary Convert() expression that casts it to type object.
                    // In this case, the Operand of the Convert expression has the original expression.
                    propertyExpression = unary.Operand as MemberExpression;
                }
                else
                {
                    propertyExpression = expression.Body as MemberExpression;
                }

                if (propertyExpression != null)
                {
                    var propertyName = propertyExpression.Member.Name;

                    var field    = propertyExpression.Member.DeclaringType.GetField(propertyName);
                    var property = propertyExpression.Member.DeclaringType.GetProperty(propertyName);

                    if (field != null)
                    {
                        members.Add(field);
                    }
                    if (property != null)
                    {
                        members.Add(property);
                    }
                }
            }
            return(members.ToArray());
        }
Exemplo n.º 4
0
        /// <summary>
        /// Serializes an object to xml.
        /// </summary>
        /// <param name="serializable">The object to serialize.</param>
        /// <param name="filter">The member filter.</param>
        /// <param name="emitTypeInfo">Specifies whether the type info should be emitted when serializing the object.</param>
        /// <param name="version">The version of the object that should be used when serializing the object.</param>
        /// <param name="provider">An object that supplies culture-specific formatting information.</param>
        /// <returns>The xml document with the serialized object.</returns>
        /// <exception cref="SerializationException">Is thrown if the serialization cannot be performed.</exception>
        public static XDocument ToXmlDocument <TFilter>(
            this IXPathSerializable serializable,
            MemberFilter <TFilter> filter = null,
            bool emitTypeInfo             = false,
            int version = 0,
            IFormatProvider provider = null)
        {
            var useMembers = GetFilterMembers <TFilter>(serializable, filter);

            return(ToXmlInternal(
                       new XDocument(),
                       serializable,
                       objectsAlreadySerialized: new HashSet <object>(),
                       useMembers: useMembers,
                       parentMapping: null,
                       emitTypeInfo: emitTypeInfo,
                       version: version,
                       provider: provider,
                       resolver: null));
        }
Exemplo n.º 5
0
        private static IXPathSerializable LoadFromXmlInternal(
            XDocument document,
            IXPathSerializable serializable,
            MemberInfo[] useMembers,
            Mapping parentMapping,
            int version,
            IFormatProvider provider,
            XmlNamespaceManager resolver)
        {
            // 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);
            }

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

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

            LoadMembersFromXml(
                document,
                serializable,
                membersToLoad.ToArray(),
                useMembers,
                parentMapping,
                version,
                provider,
                resolver);

            return(serializable);
        }
Exemplo n.º 6
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);
                }
            }
        }
Exemplo n.º 7
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);
                    }
                }
            }
        }
Exemplo n.º 8
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);
        }