JD2022-TU1/main/tools/framework/JD.Serializers/Xml/XmlSerializer.cs

190 lines
5.3 KiB
C#

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
{
/// <summary>
/// Base class for all Xml Serializers
/// </summary>
public abstract class XmlSerializer : IDisposable
{
#region Variables
/// <summary>
/// Name of the root element of all Xml documents read or written by XmlSerializers
/// </summary>
public const string RootElement = "TeaBox";
/// <summary>
/// Name of the attribute representing the version of all Xml documents read of written by XmlSerializer
/// </summary>
protected const string VersionAttribute = "version";
/// <summary>
/// Default Array Separator.
/// </summary>
protected const char DefaultArraySeparator = ',';
private bool m_disposed;
private readonly string m_streamName;
private readonly TypeConverterCache m_cache = new TypeConverterCache();
#endregion
#region IDisposable Members
/// <summary>
/// Finalizer.
/// </summary>
~XmlSerializer()
{
System.Diagnostics.Debug.Assert(!m_disposed);
Dispose(false);
}
/// <summary>
/// Disposes the serializer.
/// </summary>
public void Dispose()
{
if (!m_disposed)
{
Dispose(true);
GC.SuppressFinalize(this);
m_disposed = true;
}
}
/// <summary>
/// Protected implementation of the Dispose pattern.
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
}
#endregion
/// <summary>
/// Default constructor. Must be called by base class to initialize the stream's name.
/// </summary>
/// <param name="stream"></param>
protected XmlSerializer(System.IO.Stream stream)
: this(stream, null)
{ }
/// <summary>
/// Constructor with a fallback filename.
/// </summary>
/// <param name="stream"></param>
/// <param name="fallbackFileName"></param>
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
/// <summary>
/// Name of the file if the steam is a FileStream, null otherwise.
/// </summary>
public string FileName
{
get
{
return m_streamName;
}
}
/// <summary>
/// Whether this <see cref="XmlSerializer"/> is disposed.
/// </summary>
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;
}
/// <summary>
/// Starts an xml element.
/// </summary>
/// <remarks>
/// Disposing the returned object will end the element.
/// </remarks>
/// <param name="element">Name of the xml element to start.</param>
public abstract IXmlElement StartElement(string element);
/// <summary>
/// Helper function to write and then read xml data.
/// </summary>
/// <param name="write">Action that writes data.</param>
/// <param name="read">Action that reads the written data.</param>
public static void WriteRead(Action<XmlSerializerWriter> write, Action<XmlSerializerReader> 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
}
}