mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-07 00:35:12 +00:00
feat: Begin implementing XmlConverters
This commit is contained in:
155
ICD.Common.Utils/Xml/AbstractGenericXmlConverter.cs
Normal file
155
ICD.Common.Utils/Xml/AbstractGenericXmlConverter.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Xml;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Xml
|
||||
{
|
||||
public abstract class AbstractGenericXmlConverter<T> : AbstractXmlConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of T.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual T Instantiate()
|
||||
{
|
||||
return ReflectionUtils.CreateInstance<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="elementName"></param>
|
||||
/// <param name="value">The value.</param>
|
||||
public sealed override void WriteXml(IcdXmlTextWriter writer, string elementName, object value)
|
||||
{
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteElementString(elementName, null);
|
||||
return;
|
||||
}
|
||||
|
||||
WriteXml(writer, elementName, (T)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="elementName"></param>
|
||||
/// <param name="value">The value.</param>
|
||||
[PublicAPI]
|
||||
public void WriteXml(IcdXmlTextWriter writer, string elementName, T value)
|
||||
{
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteElementString(elementName, null);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteStartElement(elementName);
|
||||
{
|
||||
WriteAttributes(writer, value);
|
||||
WriteElements(writer, value);
|
||||
}
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to write attributes to the root element.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="value"></param>
|
||||
protected virtual void WriteAttributes(IcdXmlTextWriter writer, T value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to write elements to the writer.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="value"></param>
|
||||
protected virtual void WriteElements(IcdXmlTextWriter writer, T value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The XmlReader to read from.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public sealed override object ReadXml(IcdXmlReader reader)
|
||||
{
|
||||
return ReadXmlTyped(reader);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The XmlReader to read from.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
[PublicAPI]
|
||||
public virtual T ReadXmlTyped(IcdXmlReader reader)
|
||||
{
|
||||
T output = default(T);
|
||||
bool instantiated = false;
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement)
|
||||
break;
|
||||
|
||||
if (!instantiated)
|
||||
{
|
||||
instantiated = true;
|
||||
output = Instantiate();
|
||||
}
|
||||
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.Attribute:
|
||||
ReadAttribute(reader, output);
|
||||
break;
|
||||
|
||||
case XmlNodeType.Element:
|
||||
ReadElement(reader, output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to handle the current attribute.
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="instance"></param>
|
||||
protected virtual void ReadAttribute(IcdXmlReader reader, T instance)
|
||||
{
|
||||
// Skip the attribute
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override to handle the current element.
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="instance"></param>
|
||||
protected virtual void ReadElement(IcdXmlReader reader, T instance)
|
||||
{
|
||||
// Skip the element
|
||||
reader.ReadOuterXml();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
ICD.Common.Utils/Xml/AbstractXmlConverter.cs
Normal file
25
ICD.Common.Utils/Xml/AbstractXmlConverter.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Xml
|
||||
{
|
||||
public abstract class AbstractXmlConverter : IXmlConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="elementName"></param>
|
||||
/// <param name="value">The value.</param>
|
||||
public abstract void WriteXml(IcdXmlTextWriter writer, string elementName, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The XmlReader to read from.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
[PublicAPI]
|
||||
public abstract object ReadXml(IcdXmlReader reader);
|
||||
}
|
||||
}
|
||||
32
ICD.Common.Utils/Xml/DefaultXmlConverter.cs
Normal file
32
ICD.Common.Utils/Xml/DefaultXmlConverter.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace ICD.Common.Utils.Xml
|
||||
{
|
||||
public sealed class DefaultXmlConverter : AbstractXmlConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="elementName"></param>
|
||||
/// <param name="value">The value.</param>
|
||||
public override void WriteXml(IcdXmlTextWriter writer, string elementName, object value)
|
||||
{
|
||||
string elementString = IcdXmlConvert.ToString(value);
|
||||
|
||||
writer.WriteElementString(elementName, elementString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The XmlReader to read from.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public override object ReadXml(IcdXmlReader reader)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
22
ICD.Common.Utils/Xml/IXmlConverter.cs
Normal file
22
ICD.Common.Utils/Xml/IXmlConverter.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace ICD.Common.Utils.Xml
|
||||
{
|
||||
public interface IXmlConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="elementName"></param>
|
||||
/// <param name="value">The value.</param>
|
||||
void WriteXml(IcdXmlTextWriter writer, string elementName, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the XML representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The XmlReader to read from.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
object ReadXml(IcdXmlReader reader);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using ICD.Common.Utils.IO;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.CrestronXml;
|
||||
#else
|
||||
@@ -9,6 +11,58 @@ namespace ICD.Common.Utils.Xml
|
||||
{
|
||||
public static class IcdXmlConvert
|
||||
{
|
||||
/// <summary>
|
||||
/// Serializes the given instance to an xml string.
|
||||
/// </summary>
|
||||
/// <param name="elementName"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string SerializeObject(string elementName, object value)
|
||||
{
|
||||
if (value == null)
|
||||
return ToString(null);
|
||||
|
||||
IXmlConverter converter = XmlConverterAttribute.GetConverterForInstance(value);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
using (IcdStringWriter stringWriter = new IcdStringWriter(builder))
|
||||
{
|
||||
using (IcdXmlTextWriter writer = new IcdXmlTextWriter(stringWriter))
|
||||
converter.WriteXml(writer, elementName, value);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the given xml to an instance of the given type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="xml"></param>
|
||||
/// <returns></returns>
|
||||
public static object DeserializeObject<T>(string xml)
|
||||
{
|
||||
return (T)DeserializeObject(typeof(T), xml);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the given xml to an instance of the given type.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="xml"></param>
|
||||
/// <returns></returns>
|
||||
private static object DeserializeObject(Type type, string xml)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
IXmlConverter converter = XmlConverterAttribute.GetConverterForInstance(type);
|
||||
|
||||
using (IcdXmlReader reader = new IcdXmlReader(xml))
|
||||
return converter.ReadXml(reader);
|
||||
}
|
||||
|
||||
public static string ToString(int value)
|
||||
{
|
||||
return XmlConvert.ToString(value);
|
||||
|
||||
91
ICD.Common.Utils/Xml/XmlConverterAttribute.cs
Normal file
91
ICD.Common.Utils/Xml/XmlConverterAttribute.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ICD.Common.Utils.Attributes;
|
||||
|
||||
namespace ICD.Common.Utils.Xml
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
|
||||
public sealed class XmlConverterAttribute : AbstractIcdAttribute
|
||||
{
|
||||
private static readonly Dictionary<Type, IXmlConverter> s_InstanceTypeToConverter;
|
||||
private static readonly Dictionary<Type, IXmlConverter> s_ConverterTypeToConverter;
|
||||
|
||||
private readonly Type m_ConverterType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the converter type.
|
||||
/// </summary>
|
||||
public Type ConverterType { get { return m_ConverterType; } }
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor.
|
||||
/// </summary>
|
||||
static XmlConverterAttribute()
|
||||
{
|
||||
s_InstanceTypeToConverter = new Dictionary<Type, IXmlConverter>();
|
||||
s_ConverterTypeToConverter = new Dictionary<Type, IXmlConverter>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="converterType"></param>
|
||||
public XmlConverterAttribute(Type converterType)
|
||||
{
|
||||
m_ConverterType = converterType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the XML converter for the given instance.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static IXmlConverter GetConverterForInstance(object value)
|
||||
{
|
||||
return value == null ? LazyLoadConverter(typeof(DefaultXmlConverter)) : GetConverterForType(value.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the XML converter for the given type.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static IXmlConverter GetConverterForType(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
IXmlConverter converter;
|
||||
if (!s_InstanceTypeToConverter.TryGetValue(type, out converter))
|
||||
{
|
||||
XmlConverterAttribute attribute = AttributeUtils.GetClassAttribute<XmlConverterAttribute>(type);
|
||||
Type converterType = attribute == null ? typeof(DefaultXmlConverter) : attribute.ConverterType;
|
||||
|
||||
converter = LazyLoadConverter(converterType);
|
||||
s_InstanceTypeToConverter[type] = converter;
|
||||
}
|
||||
|
||||
return converter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lazy-loads the converter of the given type.
|
||||
/// </summary>
|
||||
/// <param name="converterType"></param>
|
||||
/// <returns></returns>
|
||||
private static IXmlConverter LazyLoadConverter(Type converterType)
|
||||
{
|
||||
if (converterType == null)
|
||||
throw new ArgumentNullException("converterType");
|
||||
|
||||
IXmlConverter converter;
|
||||
if (!s_ConverterTypeToConverter.TryGetValue(converterType, out converter))
|
||||
{
|
||||
converter = ReflectionUtils.CreateInstance(converterType) as IXmlConverter;
|
||||
s_ConverterTypeToConverter[converterType] = converter;
|
||||
}
|
||||
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user