Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#

A Fast/Compact Serialization Framework

Rate me:
Please Sign up or sign in to vote.
4.85/5 (37 votes)
13 Oct 2010GPL35 min read 281.9K   1.2K   175  
A framework for object serializiation/deserialization that is many times faster and yields a compact output.
/*

OpenNxSerialization Framework
Copyright (C) 2006 - 2008 "NeXtreme Innovations"
[The Next Xtreme Innovations]

This program is free software, distributed under the terms of
the GNU General Public License Version 2. See the "License.txt" file
at the top of the source tree.

*/
using System;
using System.Collections;

using NeXtreme.OpenNxSerialization.Surrogates;

namespace NeXtreme.OpenNxSerialization
{
    /// <summary>
    /// Provides the common type identification system. Takes care of registering type surrogates
    /// and type handles. 
    /// </summary>
    public sealed class NxTypeSurrogateSelector : INxTypeSurrogateSelector
    {
        /// <summary>
        /// Minimum id that can be assigned to a user defined type. 
        /// </summary>
        /// <remarks>
        /// If you specify a fixed type handle make sure it is in the range <see cref="NxTypeSurrogateSelector.MinTypeHandle"/>
        /// and <see cref="NxTypeSurrogateSelector.MaxTypeHandle"/> (inclusive).
        /// </remarks>
        public const short MinTypeHandle = short.MinValue + 512;

        /// <summary>
        /// Maximum id that can be assigned to a user defined type. 
        /// </summary>
        /// <remarks>
        /// If you specify a fixed type handle make sure it is in the range <see cref="NxTypeSurrogateSelector.MinTypeHandle"/>
        /// and <see cref="NxTypeSurrogateSelector.MaxTypeHandle"/> (inclusive).
        /// </remarks>
        public const short MaxTypeHandle = short.MaxValue;

        private static INxTypeSurrogateSelector msDefault;
        private INxSerializationSurrogate mNullSurrogate;
        private INxSerializationSurrogate mDefaultSurrogate;
        private IDictionary mTypeSurrogateMap;
        private IDictionary mHandleSurrogateMap;
        private short mNewTypeHandle;

        /// <summary>
        /// Static constructor registers built-in surrogates with the system.
        /// </summary>
        static NxTypeSurrogateSelector()
        {
            msDefault = new NxTypeSurrogateSelector();
        }

        /// <summary>
        /// Constructs the object with built-in surrogates.
        /// </summary>
        public NxTypeSurrogateSelector()
            : this(true)
        {
        }

        /// <summary>
        /// Constructs the object with or without built-in surrogates.
        /// </summary>
        /// <param name="useBuiltinSurrogates">If true built-in surrogates are 
        /// registered</param>
        public NxTypeSurrogateSelector(bool useBuiltinSurrogates)
        {
            mTypeSurrogateMap = /*Hashtable.Synchronized*/(new Hashtable(100));
            mHandleSurrogateMap = /*Hashtable.Synchronized*/(new Hashtable(100));

            //mTypeSurrogateMap = Hashtable.Synchronized(new Hashtable(100, 0.1f));
            //mHandleSurrogateMap = Hashtable.Synchronized(new Hashtable(100, 0.1f));
            mNewTypeHandle = MinTypeHandle;

            mNullSurrogate = new NxNullSerializationSurrogate();
            mDefaultSurrogate = new NxObjectSerializationSurrogate(typeof(object));

            Register(mNullSurrogate, 0);
            Register(mDefaultSurrogate, 1);
            Register(new NxObjRefSerializationSurrogate(), 2);

            if (useBuiltinSurrogates)
            {
                RegisterBuiltinSurrogates();
            }
        }

        /// <summary>
        /// Returns the default type surrogate selector object
        /// </summary>
        /// <value>The default <see cref="NxTypeSurrogateSelector"/> object</value>
        public static INxTypeSurrogateSelector Default
        {
            get { return NxTypeSurrogateSelector.msDefault; }
            set { NxTypeSurrogateSelector.msDefault = value; }
        }

        /// <summary>
        /// Gets and object that can be used to synchronize access to the <see cref="NxTypeSurrogateSelector"/>
        /// </summary>
        public object SyncRoot
        {
            get { return mTypeSurrogateMap.SyncRoot; }
        }

        /// <summary>
        /// Returns the default type surrogate for null
        /// </summary>
        /// <value>The default <see cref="INxSerializationSurrogate"/> for null</value>
        public INxSerializationSurrogate NullSurrogate
        {
            get { return mNullSurrogate; }
            set { mNullSurrogate = value; }
        }

        /// <summary>
        /// Returns the default type surrogate
        /// </summary>
        /// <remarks>
        /// The default surrogate is used when no specialized surrogate is found for a type
        /// </remarks>
        /// <value>The default <see cref="INxSerializationSurrogate"/> object</value>
        public INxSerializationSurrogate DefaultSurrogate
        {
            get { return mDefaultSurrogate; }
            set { mDefaultSurrogate = value; }
        }

        /// <summary>
        /// Use this to determine whether the specified surrogate is a built-in surrogate
        /// </summary>
        /// <returns>
        /// Returns true if the specified surrogate is a built-in surrogate
        /// </returns>
        public bool IsBuiltinSurrogate(INxSerializationSurrogate surrogate)
        {
            if (surrogate == null)
                throw new ArgumentNullException("surrogate");

            return typeof(INxBuiltinSerializationSurrogate).IsAssignableFrom(surrogate.GetType());
        }

        /// <summary>
        /// Returns an object that can be used to iterate over the collection of surrogates
        /// </summary>
        /// <returns>
        /// An <see cref="IEnumerator"/> that can be used to iterate over the collection of surrogates
        /// </returns>
        public IEnumerator GetEnumerator()
        {
            return mTypeSurrogateMap.Values.GetEnumerator();
        }

        /// <summary>
        /// Finds and returns an appropriate <see cref="INxSerializationSurrogate"/> for the given
        /// object.
        /// </summary>
        /// <param name="graph">specified object</param>
        /// <returns><see cref="INxSerializationSurrogate"/> object</returns>
        public INxSerializationSurrogate GetSurrogateForObject(object graph)
        {
            if (graph == null)
                return mNullSurrogate;
            return GetSurrogateForType(graph.GetType());
        }

        /// <summary>
        /// Finds and returns an appropriate <see cref="INxSerializationSurrogate"/> for the given
        /// type. 
        /// </summary>
        /// <param name="type">specified type</param>
        /// <returns><see cref="INxSerializationSurrogate"/> object</returns>
        /// <remarks>
        /// If no surrogate is found for the specified <paramref name="type"/>, the <see cref="Default"/>
        /// surrogate is returned.
        /// </remarks>
        public INxSerializationSurrogate GetSurrogateForType(Type type)
        {
            INxSerializationSurrogate surrogate = (INxSerializationSurrogate)mTypeSurrogateMap[type];
            if (surrogate == null)
                surrogate = mDefaultSurrogate;
            return surrogate;
        }

        /// <summary>
        /// Finds and returns <see cref="INxSerializationSurrogate"/> for the given
        /// type. Allows you to inhibit the usage of default surrogate.
        /// </summary>
        /// <param name="type">specified type</param>
        /// <param name="strict">Specifies whether the default surrogate will be returned.</param>
        /// <returns><see cref="INxSerializationSurrogate"/> object</returns>
        public INxSerializationSurrogate GetSurrogateForType(Type type, bool strict)
        {
            INxSerializationSurrogate surrogate = (INxSerializationSurrogate)mTypeSurrogateMap[type];
            if (!strict && surrogate == null)
                surrogate = mDefaultSurrogate;
            return surrogate;
        }

        /// <summary>
        /// Finds and returns an appropriate <see cref="INxSerializationSurrogate"/> for the given
        /// type handle.
        /// </summary>
        /// <param name="handle">type handle</param>
        /// <returns><see cref="INxSerializationSurrogate"/> object</returns>
        public INxSerializationSurrogate GetSurrogateForTypeHandle(short handle)
        {
            INxSerializationSurrogate surrogate = (INxSerializationSurrogate)mHandleSurrogateMap[handle];
            if (surrogate == null)
                surrogate = mDefaultSurrogate;
            return surrogate;
        }

        #region /       INxSerializationSurrogate registration specific        /

        /// <summary>
        /// Registers the specified <see cref="INxSerializationSurrogate"/> with the system.
        /// </summary>
        /// <param name="surrogate">specified surrogate</param>
        /// <returns>false if the surrogated type already has a surrogate</returns>
        public bool Register(INxSerializationSurrogate surrogate)
        {
            if (surrogate == null)
                throw new ArgumentNullException("surrogate");

            for (;;)
            {
                try
                {
                    return Register(surrogate, ++mNewTypeHandle);
                }
                catch (ArgumentException) { }
                catch (Exception)
                {
                    throw;
                }
            }
        }

        /// <summary>
        /// Registers the specified <see cref="INxSerializationSurrogate"/> with the given type handle.
        /// Gives more control over the way type handles are generated by the system and allows the 
        /// user to supply *HARD* handles for better interoperability among applications.
        /// </summary>
        /// <param name="surrogate">specified surrogate</param>
        /// <param name="typeHandle">specified HARD handle for type</param>
        /// <returns>false if the surrogated type already has a surrogate</returns>
        /// <remarks>
        /// <paramref name="typeHandle"/> must be in the range <see cref="NxTypeSurrogateSelector.MinTypeHandle"/> 
        /// and <see cref="NxTypeSurrogateSelector.MaxTypeHandle"/> (inclusive).
        /// </remarks>
        public bool Register(INxSerializationSurrogate surrogate, short typeHandle)
        {
            if (!IsBuiltinSurrogate(surrogate))
            {
                if (typeHandle < MinTypeHandle)
                {
                    throw new ArgumentException(Resources.Surrogates_HandleOutOfRange);
                }
            }

            lock (mTypeSurrogateMap.SyncRoot)
            {
                if (mHandleSurrogateMap.Contains(typeHandle))
                    throw new ArgumentException(Resources.Surrogates_AlreadyRegistered);

                if (!mTypeSurrogateMap.Contains(surrogate.ActualType))
                {
                    surrogate.TypeHandle = typeHandle;
                    mTypeSurrogateMap.Add(surrogate.ActualType, surrogate);
                    mHandleSurrogateMap.Add(surrogate.TypeHandle, surrogate);
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Unregisters the specified <see cref="INxSerializationSurrogate"/> from the system.
        /// </summary>
        /// <param name="surrogate">specified surrogate</param>
        public void Unregister(INxSerializationSurrogate surrogate)
        {
            if (surrogate == null)
                throw new ArgumentNullException("surrogate");

            lock (mTypeSurrogateMap.SyncRoot)
            {
                mTypeSurrogateMap.Remove(surrogate.ActualType);
                mHandleSurrogateMap.Remove(surrogate.TypeHandle);
            }
        }

        /// <summary>
        /// Unregisters all surrogates, except null and default ones.
        /// </summary>
        public void Clear()
        {
            lock (mTypeSurrogateMap.SyncRoot)
            {
                mTypeSurrogateMap.Clear();
                mHandleSurrogateMap.Clear();

                mNewTypeHandle = MinTypeHandle;
                Register(mNullSurrogate, 0);
                Register(mDefaultSurrogate, 1);
                Register(new NxObjRefSerializationSurrogate(), 2);
            }
        }

        #endregion

        #region /       Builtin surrogates        /

        /// <summary>
        /// Registers built-in surrogates with the system.
        /// </summary>
        public void RegisterBuiltinSurrogates()
        {
            short typeHandle = 32;

            lock (mTypeSurrogateMap.SyncRoot)
            {
                Register(new NxSerializationInfoSurrogate(), typeHandle++);

                Register(new NxBooleanSerializationSurrogate(), typeHandle++);
                Register(new NxByteSerializationSurrogate(), typeHandle++);
                Register(new NxCharSerializationSurrogate(), typeHandle++);
                Register(new NxSingleSerializationSurrogate(), typeHandle++);
                Register(new NxDoubleSerializationSurrogate(), typeHandle++);
                Register(new NxDecimalSerializationSurrogate(), typeHandle++);
                Register(new NxInt16SerializationSurrogate(), typeHandle++);
                Register(new NxInt32SerializationSurrogate(), typeHandle++);
                Register(new NxInt64SerializationSurrogate(), typeHandle++);
                Register(new NxStringSerializationSurrogate(), typeHandle++);
                Register(new NxDateTimeSerializationSurrogate(), typeHandle++);
                Register(new NxGuidSerializationSurrogate(), typeHandle++);
                Register(new NxSByteSerializationSurrogate(), typeHandle++);
                Register(new NxUInt16SerializationSurrogate(), typeHandle++);
                Register(new NxUInt32SerializationSurrogate(), typeHandle++);
                Register(new NxUInt64SerializationSurrogate(), typeHandle++);

                Register(new NxObjectArraySerializationSurrogate(), typeHandle++);
                Register(new NxBooleanArraySerializationSurrogate(), typeHandle++);
                Register(new NxByteArraySerializationSurrogate(), typeHandle++);
                Register(new NxCharArraySerializationSurrogate(), typeHandle++);
                Register(new NxSingleArraySerializationSurrogate(), typeHandle++);
                Register(new NxDoubleArraySerializationSurrogate(), typeHandle++);
                Register(new NxDecimalArraySerializationSurrogate(), typeHandle++);
                Register(new NxInt16ArraySerializationSurrogate(), typeHandle++);
                Register(new NxInt32ArraySerializationSurrogate(), typeHandle++);
                Register(new NxInt64ArraySerializationSurrogate(), typeHandle++);
                Register(new NxStringArraySerializationSurrogate(), typeHandle++);
                Register(new NxDateTimeArraySerializationSurrogate(), typeHandle++);
                Register(new NxGuidArraySerializationSurrogate(), typeHandle++);
                Register(new NxSByteArraySerializationSurrogate(), typeHandle++);
                Register(new NxUInt16ArraySerializationSurrogate(), typeHandle++);
                Register(new NxUInt32ArraySerializationSurrogate(), typeHandle++);
                Register(new NxUInt64ArraySerializationSurrogate(), typeHandle++);

                // TODO: Would a custom surrogate be faster?
                Register(new NxISerializableSerializationSurrogate(typeof(Exception)), typeHandle++);
                Register(new NxISerializableSerializationSurrogate(typeof(WeakReference)), typeHandle++);

                Register(new NxArraySerializationSurrogate(typeof(Array)), typeHandle++);
                Register(new NxIListSerializationSurrogate(typeof(IList)), typeHandle++);
                Register(new NxIListSerializationSurrogate(typeof(ArrayList)), typeHandle++);
                Register(new NxIDictionarySerializationSurrogate(typeof(IDictionary)), typeHandle++);
                Register(new NxIDictionarySerializationSurrogate(typeof(Hashtable)), typeHandle++);
                Register(new NxIDictionarySerializationSurrogate(typeof(SortedList)), typeHandle++);

                Register(new NxNullableArraySerializationSurrogate<Boolean>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Byte>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Char>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Single>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Double>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Decimal>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Int16>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Int32>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Int64>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<DateTime>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<Guid>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<SByte>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<UInt16>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<UInt32>(), typeHandle++);
                Register(new NxNullableArraySerializationSurrogate<UInt64>(), typeHandle++);

                Register(new NxHeaderSerializationSurrogate(), typeHandle++);
                Register(new NxHeaderArraySerializationSurrogate(), typeHandle++);
            }
        }

        #endregion
    }
}

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 GNU General Public License (GPLv3)


Written By
Architect
Pakistan Pakistan
Let a = b ....... (1)
a - b = a - b
a^2 - ab = a^2 - ab
a^2 - ab = a^2 - b^2 (from 1)
a (a - b) = (a + b) (a - b)
a = (a + b) ...... (2)

if a = 1
1 = (1 + 1) (from 1 & 2)
1 = 2 !!

Comments and Discussions