wasSharpNET – Rev 16

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
// Based on: Danilow @ https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using wasSharp;

namespace wasSharpNET.Serialization
{
    public static class XmlSerializerCache
    {
        private static ReaderWriterLockSlim SerializerCacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
        private static Dictionary<string, XmlSerializer> SerializerCache = new Dictionary<string, XmlSerializer>();

        public static XmlSerializer GetSerializer<T>()
        {
            return GetSerializer<T>(null);
        }

        public static XmlSerializer GetSerializer<T>(Type[] ExtraTypes)
        {
            return GetSerializer(typeof(T), ExtraTypes);
        }

        public static XmlSerializer GetSerializer(Type MainTypeForSerialization)
        {
            return GetSerializer(MainTypeForSerialization, null);
        }

        public static XmlSerializer GetSerializer(Type MainTypeForSerialization, Type[] ExtraTypes)
        {
            string Signature = MainTypeForSerialization.FullName;
            if (ExtraTypes != null)
            {
                foreach (Type Tp in ExtraTypes)
                    Signature += "-" + Tp.FullName;
            }

            SerializerCacheLock.EnterReadLock();
            XmlSerializer XmlEventSerializer = null;
            if (SerializerCache.TryGetValue(Signature, out XmlEventSerializer))
            {
                SerializerCacheLock.ExitReadLock();
                return XmlEventSerializer;
            }
            SerializerCacheLock.ExitReadLock();

            if (ExtraTypes == null)
                return new XmlSerializer(MainTypeForSerialization);

            XmlEventSerializer = new XmlSerializer(MainTypeForSerialization, ExtraTypes);
            SerializerCacheLock.EnterWriteLock();
            SerializerCache.Add(Signature, XmlEventSerializer);
            SerializerCacheLock.ExitWriteLock();

            return XmlEventSerializer;
        }

        public static T Deserialize<T>(XDocument XmlData)
        {
            return Deserialize<T>(XmlData, null);
        }

        public static T Deserialize<T>(XDocument XmlData, Type[] ExtraTypes)
        {
            try
            {
                using (var XmlReader = XmlData.Root.CreateReader())
                {
                    return (T)GetSerializer<T>(ExtraTypes).Deserialize(XmlReader);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Could not deserialize to " + typeof(T).Name, ex);
            }
        }

        public static T Deserialize<T>(string XmlData)
        {
            return Deserialize<T>(XmlData, null);
        }

        public static T Deserialize<T>(string XmlData, Type[] ExtraTypes)
        {
            try
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (StreamWriter streamWriter = new StreamWriter(memoryStream))
                    {
                        streamWriter.Write(XmlData);
                        streamWriter.Flush();
                        memoryStream.Position = 0;
                        return (T)GetSerializer<T>(ExtraTypes).Deserialize(memoryStream);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Could not deserialize to " + typeof(T).Name, ex);
            }
        }

        public static XDocument Serialize<T>(T Object, Type[] ExtraTypes)
        {
            try
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (StreamReader streamReader = new StreamReader(memoryStream))
                    {
                        using (var xmlWriter = XmlWriter.Create(memoryStream, new XmlWriterSettings { Indent = true }))
                        {
                            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                            ns.Add(string.Empty, string.Empty);
                            GetSerializer<T>(ExtraTypes).Serialize(xmlWriter, Object, ns);
                            xmlWriter.Flush();
                            memoryStream.Position = 0L;
                            return XDocument.Load(streamReader, LoadOptions.None);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Could not serialize from " + typeof(T).Name + " to xml string", ex);
            }
        }

        public static XDocument Serialize<T>(T Object)
        {
            return Serialize(Object, null);
        }

        public static T Deserialize<T>(StreamReader streamReader)
        {
            return Deserialize<T>(streamReader.ReadToEnd(), null);
        }

        public static T Deserialize<T>(Stream stream)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                stream.CopyTo(memoryStream);
                memoryStream.Position = 0L;
                using (var streamReader = new StreamReader(memoryStream))
                {
                    return Deserialize<T>(streamReader.ReadToEnd(), null);
                }
            }
        }

        public static void Serialize<T>(Stream stream, T value)
        {
            Serialize(value, null).Save(stream);
        }

        public static void Serialize<T>(StreamWriter streamWriter, T value)
        {
            Serialize(value, null).Save(streamWriter);
        }

        public static void Serialize<T>(StringWriter stringWriter, T value)
        {
            Serialize(value, null).Save(stringWriter);
        }

        public static T Deserialize<T>(TextReader reader)
        {
            return Deserialize<T>(reader.ReadToEnd(), null);
        }
    }
}