using System; using System.ComponentModel; using System.IO; using System.Text; using JD.Kernel.StaticHelpers; using JD.Reflection; using JD.Serializers.Stream; namespace JD.Serializers.Xml { /// /// Base class for all Xml Serializers /// public abstract class XmlSerializer : IDisposable { #region Variables /// /// Name of the root element of all Xml documents read or written by XmlSerializers /// public const string RootElement = "TeaBox"; /// /// Name of the attribute representing the version of all Xml documents read of written by XmlSerializer /// protected const string VersionAttribute = "version"; /// /// Default Array Separator. /// protected const char DefaultArraySeparator = ','; private bool m_disposed; private readonly string m_streamName; private readonly TypeConverterCache m_cache = new TypeConverterCache(); #endregion #region IDisposable Members /// /// Finalizer. /// ~XmlSerializer() { System.Diagnostics.Debug.Assert(!m_disposed); Dispose(false); } /// /// Disposes the serializer. /// public void Dispose() { if (!m_disposed) { Dispose(true); GC.SuppressFinalize(this); m_disposed = true; } } /// /// Protected implementation of the Dispose pattern. /// /// protected virtual void Dispose(bool disposing) { } #endregion /// /// Default constructor. Must be called by base class to initialize the stream's name. /// /// protected XmlSerializer(System.IO.Stream stream) : this(stream, null) { } /// /// Constructor with a fallback filename. /// /// /// protected XmlSerializer(System.IO.Stream stream, string fallbackFileName) { Throw.IfNull(stream, "stream"); FileStream fileStream = FindFileStream(stream); m_streamName = fileStream != null ? FileUtility.FormatPath(fileStream.Name) : fallbackFileName; } #region Properties /// /// Name of the file if the steam is a FileStream, null otherwise. /// public string FileName { get { return m_streamName; } } /// /// Whether this is disposed. /// public bool IsDisposed { get { return m_disposed; } } public static Encoding Encoding { get { return Encoding.UTF8; } } #endregion #region Methods private static FileStream FindFileStream(System.IO.Stream stream) { IStreamWrapper wrapper; do { wrapper = stream as IStreamWrapper; if (wrapper != null) { stream = wrapper.UnderlyingStream; } } while (wrapper != null); return stream as FileStream; } /// /// Starts an xml element. /// /// /// Disposing the returned object will end the element. /// /// Name of the xml element to start. public abstract IXmlElement StartElement(string element); /// /// Helper function to write and then read xml data. /// /// Action that writes data. /// Action that reads the written data. public static void WriteRead(Action write, Action read) { Throw.IfNull(write, "write"); Throw.IfNull(read, "read"); byte[] writtenData; using (MemoryStream writeStream = new MemoryStream()) { using (XmlSerializerWriter writer = new XmlSerializerWriter(writeStream)) using (writer.StartElement("PlaceHolder")) { write(writer); } writeStream.Close(); writtenData = writeStream.ToArray(); } using (MemoryStream readStream = new MemoryStream(writtenData)) using (XmlSerializerReader reader = new XmlSerializerReader(readStream)) using (reader.StartElement("PlaceHolder")) { read(reader); } } protected TypeConverter GetConverter(Type type) { return m_cache.GetConverter(type); } #endregion } }