Click here to Skip to main content
15,896,259 members
Articles / Mobile Apps / Windows Mobile

XML Serialization of Generic Dictionary, Multidimensional Array, and Inherited Type, with sharpSerializer .NET

Rate me:
Please Sign up or sign in to vote.
4.92/5 (48 votes)
9 Nov 2011CPOL8 min read 251.6K   2.9K   122  
How to serialize to XML, any generic, derived, or other complex type, which XMLSerializer cannot serialize
#region Copyright � 2010 Pawel Idzikowski [idzikowski@sharpserializer.com]

//  ***********************************************************************
//  Project: sharpSerializer
//  Web: http://www.sharpserializer.com
//  
//  This software is provided 'as-is', without any express or implied warranty.
//  In no event will the author(s) be held liable for any damages arising from
//  the use of this software.
//  
//  Permission is granted to anyone to use this software for any purpose,
//  including commercial applications, and to alter it and redistribute it
//  freely, subject to the following restrictions:
//  
//      1. The origin of this software must not be misrepresented; you must not
//        claim that you wrote the original software. If you use this software
//        in a product, an acknowledgment in the product documentation would be
//        appreciated but is not required.
//  
//      2. Altered source versions must be plainly marked as such, and must not
//        be misrepresented as being the original software.
//  
//      3. This notice may not be removed or altered from any source distribution.
//  
//  ***********************************************************************

#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Polenter.Serialization.Advanced.Binary;
using Polenter.Serialization.Advanced.Serializing;
using Polenter.Serialization.Core;
using Polenter.Serialization.Core.Binary;
using Polenter.Serialization.Serializing;

namespace Polenter.Serialization.Advanced
{
    /// <summary>
    ///   Contains logic to serialize data to a binary format. Format varies according to the used IBinaryWriter. 
    ///   Actually there are BurstBinaryWriter and SizeOptimizedBinaryWriter (see the constructor)
    /// </summary>
    public sealed class BinaryPropertySerializer : PropertySerializer
    {
        private readonly IBinaryWriter _writer;


        ///<summary>
        ///</summary>
        ///<param name = "writer"></param>
        public BinaryPropertySerializer(IBinaryWriter writer)
        {
            if (writer == null) throw new ArgumentNullException("writer");
            _writer = writer;
        }

        /// <summary>
        ///   Open the stream for writing
        /// </summary>
        /// <param name = "stream" />
        public override void Open(Stream stream)
        {
            _writer.Open(stream);
        }

        /// <summary>
        ///   Closes the stream
        /// </summary>
        public override void Close()
        {
            _writer.Close();
        }


        private void writePropertyHeader(byte elementId, string name, Type valueType)
        {
            _writer.WriteElementId(elementId);
            _writer.WriteName(name);
            _writer.WriteType(valueType);
        }

        private bool writePropertyHeaderWithReferenceId(byte elementId, ReferenceInfo info, string name, Type valueType)
        {
            if (info.Count < 2)
                // no need to write id
                return false;
            writePropertyHeader(elementId, name, valueType);
            _writer.WriteNumber(info.Id);
            return true;
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeNullProperty(PropertyTypeInfo<NullProperty> property)
        {
            writePropertyHeader(Elements.Null, property.Name, property.ValueType);
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeSimpleProperty(PropertyTypeInfo<SimpleProperty> property)
        {
            writePropertyHeader(Elements.SimpleObject, property.Name, property.ValueType);
            _writer.WriteValue(property.Property.Value);
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeMultiDimensionalArrayProperty(
            PropertyTypeInfo<MultiDimensionalArrayProperty> property)
        {
            if (!writePropertyHeaderWithReferenceId(Elements.MultiArrayWithId, property.Property.Reference, property.Name, property.ValueType))
            {
                // Property value is not referenced multiple times
                writePropertyHeader(Elements.MultiArray, property.Name, property.ValueType);
            } 

            // ElementType
            _writer.WriteType(property.Property.ElementType);

            // DimensionInfos
            writeDimensionInfos(property.Property.DimensionInfos);

            // Eintr�ge
            writeMultiDimensionalArrayItems(property.Property.Items, property.Property.ElementType);
        }

        private void writeMultiDimensionalArrayItems(IList<MultiDimensionalArrayItem> items, Type defaultItemType)
        {
            // Count
            _writer.WriteNumber(items.Count);

            // Items
            foreach (MultiDimensionalArrayItem item in items)
            {
                writeMultiDimensionalArrayItem(item, defaultItemType);
            }
        }

        private void writeMultiDimensionalArrayItem(MultiDimensionalArrayItem item, Type defaultItemType)
        {
            // Write coordinates
            _writer.WriteNumbers(item.Indexes);

            // Write Data
            SerializeCore(new PropertyTypeInfo<Property>(item.Value, defaultItemType));
        }

        private void writeDimensionInfos(IList<DimensionInfo> dimensionInfos)
        {
            // count
            _writer.WriteNumber(dimensionInfos.Count);

            // items
            foreach (DimensionInfo info in dimensionInfos)
            {
                writeDimensionInfo(info);
            }
        }

        private void writeDimensionInfo(DimensionInfo info)
        {
            // Length
            _writer.WriteNumber(info.Length);

            // LowerBound
            _writer.WriteNumber(info.LowerBound);
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeSingleDimensionalArrayProperty(
            PropertyTypeInfo<SingleDimensionalArrayProperty> property)
        {
            if (!writePropertyHeaderWithReferenceId(Elements.SingleArrayWithId, property.Property.Reference, property.Name, property.ValueType))
            {
                // Property value is not referenced multiple times
                writePropertyHeader(Elements.SingleArray, property.Name, property.ValueType);
            } 

            // ElementType
            _writer.WriteType(property.Property.ElementType);

            // Lower Bound
            _writer.WriteNumber(property.Property.LowerBound);

            // items
            writeItems(property.Property.Items, property.Property.ElementType);
        }

        private void writeItems(ICollection<Property> items, Type defaultItemType)
        {
            // Count
            _writer.WriteNumber(items.Count);

            // items
            foreach (Property item in items)
            {
                SerializeCore(new PropertyTypeInfo<Property>(item, defaultItemType));
            }
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeDictionaryProperty(PropertyTypeInfo<DictionaryProperty> property)
        {
            if (!writePropertyHeaderWithReferenceId(Elements.DictionaryWithId, property.Property.Reference, property.Name, property.ValueType))
            {
                // Property value is not referenced multiple times
                writePropertyHeader(Elements.Dictionary, property.Name, property.ValueType);
            } 

            // type of keys
            _writer.WriteType(property.Property.KeyType);

            // type of values
            _writer.WriteType(property.Property.ValueType);

            // Properties
            writeProperties(property.Property.Properties, property.Property.Type);

            // Items
            writeDictionaryItems(property.Property.Items, property.Property.KeyType, property.Property.ValueType);
        }

        private void writeDictionaryItems(IList<KeyValueItem> items, Type defaultKeyType, Type defaultValueType)
        {
            // count
            _writer.WriteNumber(items.Count);

            foreach (KeyValueItem item in items)
            {
                writeDictionaryItem(item, defaultKeyType, defaultValueType);
            }
        }

        private void writeDictionaryItem(KeyValueItem item, Type defaultKeyType, Type defaultValueType)
        {
            // Key
            SerializeCore(new PropertyTypeInfo<Property>(item.Key, defaultKeyType));

            // Value
            SerializeCore(new PropertyTypeInfo<Property>(item.Value, defaultValueType));
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeCollectionProperty(PropertyTypeInfo<CollectionProperty> property)
        {
            if (!writePropertyHeaderWithReferenceId(Elements.CollectionWithId, property.Property.Reference, property.Name, property.ValueType))
            {
                // Property value is not referenced multiple times
                writePropertyHeader(Elements.Collection, property.Name, property.ValueType);
            }  

            // ElementType
            _writer.WriteType(property.Property.ElementType);

            // Properties
            writeProperties(property.Property.Properties, property.Property.Type);

            //Items
            writeItems(property.Property.Items, property.Property.ElementType);
        }

        /// <summary>
        /// </summary>
        /// <param name = "property"></param>
        protected override void SerializeComplexProperty(PropertyTypeInfo<ComplexProperty> property)
        {
            if (!writePropertyHeaderWithReferenceId(Elements.ComplexObjectWithId, property.Property.Reference, property.Name, property.ValueType))
            {
                // Property value is not referenced multiple times
                writePropertyHeader(Elements.ComplexObject, property.Name, property.ValueType);                
            }            

            // Properties
            writeProperties(property.Property.Properties, property.Property.Type);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="referenceTarget"></param>
        protected override void SerializeReference(ReferenceTargetProperty referenceTarget)
        {
            writePropertyHeader(Elements.Reference, referenceTarget.Name, null);
            _writer.WriteNumber(referenceTarget.Reference.Id);
        }

        private void writeProperties(PropertyCollection properties, Type ownerType)
        {
            // How many
            _writer.WriteNumber(Convert.ToInt16(properties.Count));

            // Serialize all of them
            foreach (Property property in properties)
            {
                PropertyInfo propertyInfo = ownerType.GetProperty(property.Name);
                SerializeCore(new PropertyTypeInfo<Property>(property, propertyInfo.PropertyType));
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Polenter - Software Solutions
Germany Germany
I'm C# developer from Cologne, Germany. Here I owe a small software company. My hobby is general optimization - natural talent of all lazy people Wink | ;-)

Comments and Discussions