XML 序列化工具类

/// <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;
    }
}

 

posted @ 2025-11-25 13:26  家煜宝宝  阅读(7)  评论(0)    收藏  举报