/// <summary>
/// XML 序列化工具类
/// </summary>
public static class XmlHelper
{
#region 基本序列化/反序列化
/// <summary>
/// 将对象序列化为 XML 字符串
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="obj">要序列化的对象</param>
/// <param name="encoding">编码格式(默认UTF-8)</param>
/// <param name="omitXmlDeclaration">是否忽略XML声明</param>
/// <param name="namespaces">XML命名空间</param>
/// <returns>XML字符串</returns>
public static string Serialize<T>(T obj, Encoding encoding = null, bool omitXmlDeclaration = false, XmlSerializerNamespaces namespaces = null)
{
if (obj == null) return string.Empty;
try
{
if (encoding == null)
{
encoding = Encoding.UTF8;
}
//encoding ??= Encoding.UTF8;
var serializer = new XmlSerializer(typeof(T));
var settings = new XmlWriterSettings
{
Encoding = encoding,
Indent = true,
OmitXmlDeclaration = omitXmlDeclaration
};
using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, obj, namespaces);
return encoding.GetString(stream.ToArray());
}
}
catch (Exception ex)
{
throw new InvalidOperationException("XML序列化失败", ex);
}
}
/// <summary>
/// 将 XML 字符串反序列化为对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="xml">XML字符串</param>
/// <param name="encoding">编码格式</param>
/// <returns>反序列化后的对象</returns>
public static T Deserialize<T>(string xml, Encoding encoding = null)
{
if (string.IsNullOrWhiteSpace(xml))
return default(T);
try
{
//encoding ??= Encoding.UTF8;
if (encoding == null)
{
encoding = Encoding.UTF8;
}
var serializer = new XmlSerializer(typeof(T));
var bytes = encoding.GetBytes(xml);
using (var stream = new MemoryStream(bytes))
{
return (T)serializer.Deserialize(stream);
}
}
catch (Exception ex)
{
throw new InvalidOperationException("XML反序列化失败", ex);
}
}
#endregion
#region 文件操作
/// <summary>
/// 将对象序列化并保存到文件
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="obj">要序列化的对象</param>
/// <param name="filePath">文件路径</param>
/// <param name="encoding">编码格式</param>
public static void SaveToFile<T>(T obj, string filePath, Encoding encoding = null)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
if (string.IsNullOrWhiteSpace(filePath))
throw new ArgumentException("文件路径不能为空", nameof(filePath));
try
{
//encoding ??= Encoding.UTF8;
if (encoding == null)
{
encoding = Encoding.UTF8;
}
var xml = Serialize(obj, encoding);
var directory = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
Directory.CreateDirectory(directory);
File.WriteAllText(filePath, xml, encoding);
}
catch (Exception ex)
{
throw new InvalidOperationException($"保存XML文件失败: {filePath}", ex);
}
}
/// <summary>
/// 从文件加载并反序列化为对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="filePath">文件路径</param>
/// <param name="encoding">编码格式</param>
/// <returns>反序列化后的对象</returns>
public static T LoadFromFile<T>(string filePath, Encoding encoding = null)
{
if (string.IsNullOrWhiteSpace(filePath))
throw new ArgumentException("文件路径不能为空", nameof(filePath));
if (!File.Exists(filePath))
throw new FileNotFoundException($"XML文件不存在: {filePath}");
try
{
//encoding ??= Encoding.UTF8;
if (encoding == null)
{
encoding = Encoding.UTF8;
}
var xml = File.ReadAllText(filePath, encoding);
return Deserialize<T>(xml, encoding);
}
catch (Exception ex)
{
throw new InvalidOperationException($"加载XML文件失败: {filePath}", ex);
}
}
#endregion
#region 流操作
/// <summary>
/// 将对象序列化到流
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="obj">要序列化的对象</param>
/// <param name="stream">目标流</param>
public static void SerializeToStream<T>(T obj, Stream stream)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
if (stream == null)
throw new ArgumentNullException(nameof(stream));
try
{
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, obj);
}
catch (Exception ex)
{
throw new InvalidOperationException("序列化到流失败", ex);
}
}
/// <summary>
/// 从流反序列化为对象
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="stream">源流</param>
/// <returns>反序列化后的对象</returns>
public static T DeserializeFromStream<T>(Stream stream)
{
if (stream == null)
throw new ArgumentNullException(nameof(stream));
try
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stream);
}
catch (Exception ex)
{
throw new InvalidOperationException("从流反序列化失败", ex);
}
}
#endregion
#region 高级功能
/// <summary>
/// 验证 XML 字符串是否符合指定类型的结构
/// </summary>
/// <typeparam name="T">目标类型</typeparam>
/// <param name="xml">XML字符串</param>
/// <returns>验证结果</returns>
public static bool ValidateXml<T>(string xml)
{
if (string.IsNullOrWhiteSpace(xml))
return false;
try
{
Deserialize<T>(xml);
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 格式化 XML 字符串
/// </summary>
/// <param name="xml">XML字符串</param>
/// <returns>格式化后的XML字符串</returns>
public static string FormatXml(string xml)
{
if (string.IsNullOrWhiteSpace(xml))
return xml;
try
{
var document = new XmlDocument();
document.LoadXml(xml);
using (var writer = new StringWriter())
using (var xmlWriter = new XmlTextWriter(writer))
{
xmlWriter.Formatting = Formatting.Indented;
document.WriteTo(xmlWriter);
return writer.ToString();
}
}
catch
{
return xml;
}
}
/// <summary>
/// 创建不包含命名空间的序列化器
/// </summary>
/// <returns>XmlSerializerNamespaces</returns>
public static XmlSerializerNamespaces CreateEmptyNamespaces()
{
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("", "");
return namespaces;
}
#endregion
}
/// <summary>
/// 泛型 XML 包装器,提供更便捷的链式操作
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
public class XmlWrapper<T> where T : new()
{
private T _data;
/// <summary>
/// 当前数据对象
/// </summary>
public T Data => _data;
public XmlWrapper()
{
_data = new T();
}
public XmlWrapper(T data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
//_data = data ?? throw new ArgumentNullException(nameof(data));
}
/// <summary>
/// 从文件加载数据
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="encoding">编码格式</param>
/// <returns>当前实例</returns>
public XmlWrapper<T> LoadFromFile(string filePath, Encoding encoding = null)
{
_data = XmlHelper.LoadFromFile<T>(filePath, encoding);
return this;
}
/// <summary>
/// 保存数据到文件
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="encoding">编码格式</param>
/// <returns>当前实例</returns>
public XmlWrapper<T> SaveToFile(string filePath, Encoding encoding = null)
{
XmlHelper.SaveToFile(_data, filePath, encoding);
return this;
}
/// <summary>
/// 序列化为 XML 字符串
/// </summary>
/// <param name="encoding">编码格式</param>
/// <param name="omitXmlDeclaration">是否忽略XML声明</param>
/// <returns>XML字符串</returns>
public string ToXml(Encoding encoding = null, bool omitXmlDeclaration = false)
{
return XmlHelper.Serialize(_data, encoding, omitXmlDeclaration);
}
/// <summary>
/// 从 XML 字符串加载数据
/// </summary>
/// <param name="xml">XML字符串</param>
/// <param name="encoding">编码格式</param>
/// <returns>当前实例</returns>
public XmlWrapper<T> FromXml(string xml, Encoding encoding = null)
{
_data = XmlHelper.Deserialize<T>(xml, encoding);
return this;
}
/// <summary>
/// 更新数据
/// </summary>
/// <param name="updater">更新操作</param>
/// <returns>当前实例</returns>
public XmlWrapper<T> Update(Action<T> updater)
{
updater?.Invoke(_data);
return this;
}
}