C# generic serialization utility class.
执行IXmlSerializable或Serializable的序列核心是检查特定类型,然后将其交给序列仪。
XmlDocument Serialize<T>(T obj)
{
Type type = typeof(T);
if (type.HasAttribute<SerializableAttribute>()
| type.ImplementsInterface<IXmlSerializableAttribute>())
return XmlSerializer<T>.Serialize(obj);
throw new InvalidOperationException("Unserializable object given.");
}
为此,您应采用以下推广方法和通用序列器。
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.IO;
using System.Text;
using System.Xml.Schema;
namespace System
{
public static partial class Extensions
{
/// <summary>
/// Checks if the object <see cref="Type"/> has the specified attribute.
/// </summary>
/// <param name="type">
/// Object <see cref="Type"/> for which you want to check whether
/// whether it has <see cref="Attribute"/> specified by the <typeparamref name="T"/>.
/// </param>
public static bool HasAtribute<T>(this Type type) where T : Attribute
{
return type.GetCustomAttributes(typeof(T), true).Any();
}
/// <summary>
/// Checks if the object <see cref="Type"/> implements the specified interface.
/// </summary>
/// <param name="type">
/// Object <see cref="Type"/> for which you want to check whether
/// whether it implements the interface specified by the <paramref name="interfaceType"/> parameter.
/// </param>
/// <param name="interfaceType">
/// The <see cref="Type"/> being tested, which is an interface.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="type"/> is not a class, value type, or interface,
/// and also if <paramref name="interfaceType"/> is not an interface.
/// </exception>
/// <exception cref="ArgumentException">
/// The value <see langword="null"/> was passed as one of the parameters.
/// </exception>
/// <returns>
/// <see langword="true"/> if the object <see cref="Type"/> implements the specified interface.
/// </returns>
public static bool ImplementsInterface(this Type type, Type interfaceType)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (interfaceType == null)
throw new ArgumentNullException(nameof(interfaceType));
if (!interfaceType.IsInterface)
throw new ArgumentException("Argument must be interface.",
nameof(interfaceType));
while (type != null)
{
Type[] interfaces = type.GetInterfaces();
{
int length = interfaces.Length;
for (int i = 0; i < length; i++)
{
if (interfaces[i] == interfaceType || interfaces[i].ImplementsInterface(interfaceType))
return true;
}
}
type = type.BaseType;
}
return false;
}
/// <summary>
/// Checks if the object <see cref="Type"/> implements the specified interface.
/// </summary>
/// <typeparam name="T">
/// The type being checked, which is an interface.
/// </typeparam>
/// <param name="type">
/// Object <see cref="Type"/> for which you want to check whether
/// whether it implements the specified interface <typeparamref name="T"/>.
/// </param>
/// <returns>
/// <see langword="true"/> if the object is <see cref="Type"/>
/// implements the <typeparamref name="T"/> interface.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="type"/> is not a class, value type, or interface.
/// </exception>
/// <exception cref="ArgumentException">
/// The value <see langword="null"/> was passed as <paramref name="type"/>.
/// </exception>
public static bool ImplementsInterface<T>(this Type type) where T : class =>
ImplementsInterface(type, typeof(T));
}
}
namespace System.Xml.Serialization
{
/// <summary>
/// Serializes and deserializes <typeparamref name="T"/> objects into XML documents.
/// Allows you to control the process of encoding objects in XML.
/// </summary>
/// <typeparam name="T">Object type.</typeparam>
public static class XmlSerializer<T>
{
private static readonly XmlSerializer _serializer = new XmlSerializer(typeof(T));
private static readonly XmlWriterSettings _defaultWriterSettings = new XmlWriterSettings
{
CheckCharacters = false,
CloseOutput = false,
ConformanceLevel = ConformanceLevel.Auto,
Encoding = DefaultEncoding,
Indent = true,
IndentChars = " ",
NamespaceHandling = NamespaceHandling.OmitDuplicates,
NewLineChars = "
",
NewLineHandling = NewLineHandling.Replace,
NewLineOnAttributes = false,
OmitXmlDeclaration = false
};
private static readonly XmlReaderSettings _defaultReaderSettings = new XmlReaderSettings
{
CheckCharacters = false,
CloseInput = false,
ConformanceLevel = ConformanceLevel.Auto,
DtdProcessing = DtdProcessing.Prohibit,
IgnoreComments = true,
IgnoreProcessingInstructions = true,
IgnoreWhitespace = true,
LineNumberOffset = 0,
LinePositionOffset = 0,
MaxCharactersFromEntities = 0,
MaxCharactersInDocument = 0,
NameTable = null,
ValidationFlags = XmlSchemaValidationFlags.None,
ValidationType = ValidationType.None,
XmlResolver = null
};
/// <summary>
/// Default character encoding.
/// </summary>
public static Encoding DefaultEncoding => Encoding.UTF8;
/// <summary>
/// Default settings for the <see cref="XmlWriter" /> instance being created.
/// </summary>
public static XmlWriterSettings DefaultXmlWriterSettings => _defaultWriterSettings.Clone();
/// <summary>
/// Default settings for the <see cref="XmlReader" /> instance that is created.
/// </summary>
public static XmlReaderSettings DefaultXmlReaderSettings => _defaultReaderSettings.Clone();
/// <summary>
/// Serializes the given object and returns an XML document.
/// </summary>
/// <param name="o">
/// An instance <typeparamref name="T"/> to serialize.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance.
/// If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlWriterSettings"/>.
/// </param>
/// <returns>An instance of <see cref="XmlDocument"/> that represents given object.</returns>
public static XmlDocument Serialize(T o, XmlWriterSettings settings = null)
{
StringBuilder sb = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(sb, settings ?? DefaultXmlWriterSettings))
_serializer.Serialize(xmlWriter, o, (XmlSerializerNamespaces)null);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(sb.ToString());
return xmlDocument;
}
/// <summary>
/// Deserializes the object contained in the specified XML document.
/// </summary>
/// <param name="xmlDocument">
/// An XML document containing the serialized data.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlReader" /> instance.
/// If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlReaderSettings"/>.
/// </param>
/// <returns> The deserialized object of type <typeparamref name="T"/>. </returns>
public static T Deserialize(XmlDocument xmlDocument, XmlReaderSettings settings)
{
string text = xmlDocument.OuterXml;
using (StringReader reader = new StringReader(text))
using (XmlReader xmlReader = XmlReader.Create(reader, DefaultXmlReaderSettings))
return (T)_serializer.Deserialize(xmlReader);
}
/// <summary>
/// Returns a value indicating whether this <see cref="XmlSerializer" /> can deserialize the specified XML document.
/// </summary>
/// <param name="xmlReader">
/// <see cref="XmlReader" /> Pointing to the document to deserialize.
/// </param>
/// <returns>
/// <see langword="true" /> If this <see cref="XmlSerializer" /> can deserialize an object, <see cref="XmlReader" /> indicates; otherwise, <see langword="false" />.
/// </returns>
public static bool CanDeserialize(XmlReader xmlReader)
{
return _serializer.CanDeserialize(xmlReader);
}
}
}