Unity_数据持久化_IXmlSerializable接口

Unity数据持久化

三、XML数据持久化

3.5 IXmlSerializable接口

3.5.1 IXmlSerializable接口基础概念

什么是IXmlSerializable接口:
IXmlSerializable 是.NET框架提供的一个接口,允许类自定义XML序列化和反序列化的过程。当默认的XML序列化行为无法满足需求时,可以实现这个接口来完全控制XML的读写过程。

接口定义:

csharp 复制代码
public interface IXmlSerializable
{
    XmlSchema GetSchema();
    void ReadXml(XmlReader reader);
    void WriteXml(XmlWriter writer);
}

核心方法说明:

  • GetSchema():返回XML架构定义,通常返回null
  • ReadXml(XmlReader reader):自定义XML反序列化过程
  • WriteXml(XmlWriter writer):自定义XML序列化过程
3.5.2 实现IXmlSerializable接口

基本实现结构:

csharp 复制代码
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Schema;

public class TextData : IXmlSerializable
{
    public string text = "gsffs";
    public int age;
    public List<string> list;
    public int[] array = new int[3] { 1, 2, 3 };
    
    // 实现IXmlSerializable接口
    public XmlSchema GetSchema()
    {
        return null; // 通常返回null
    }
    
    public void ReadXml(XmlReader reader)
    {
        // 自定义反序列化逻辑
    }
    
    public void WriteXml(XmlWriter writer)
    {
        // 自定义序列化逻辑
    }
}
3.5.3 自定义XML序列化(WriteXml方法)

WriteXml方法用于控制对象如何序列化为XML格式。有三种主要的写入方式:

1. 写入属性(Attribute)

csharp 复制代码
public void WriteXml(XmlWriter writer)
{
    // 将数据作为XML元素的属性写入
    writer.WriteAttributeString("text", text);
    writer.WriteAttributeString("age", age.ToString());
}

生成的XML格式:

xml 复制代码
<TextData text="gsffs" age="25" />

2. 写入元素节点(Element)

csharp 复制代码
public void WriteXml(XmlWriter writer)
{
    // 将数据作为独立的XML元素写入
    writer.WriteElementString("text", text);
    writer.WriteElementString("age", age.ToString());
}

生成的XML格式:

xml 复制代码
<TextData>
    <text>gsffs</text>
    <age>25</age>
</TextData>

3. 写入包裹节点(复杂序列化)

csharp 复制代码
public void WriteXml(XmlWriter writer)
{
    // 使用XmlSerializer进行复杂类型的序列化
    XmlSerializer ser = new XmlSerializer(typeof(string));
    
    // 写入text字段
    writer.WriteStartElement("text1");
    ser.Serialize(writer, text);
    writer.WriteEndElement();
    
    // 写入age字段
    XmlSerializer ser2 = new XmlSerializer(typeof(int));
    writer.WriteStartElement("age");
    ser2.Serialize(writer, age);
    writer.WriteEndElement();
}

生成的XML格式:

xml 复制代码
<TextData>
    <text1>gsffs</text1>
    <age>25</age>
</TextData>
3.5.4 自定义XML反序列化(ReadXml方法)

ReadXml方法用于控制如何从XML格式反序列化为对象。有三种主要的读取方式:

1. 读取属性(Attribute)

csharp 复制代码
public void ReadXml(XmlReader reader)
{
    // 从XML元素的属性中读取数据
    age = int.Parse(reader.GetAttribute("age"));
    text = reader.GetAttribute("text");
}

2. 读取元素节点(Element)

csharp 复制代码
public void ReadXml(XmlReader reader)
{
    // 方法1:手动控制读取过程
    reader.Read(); // 读取text节点
    reader.Read(); // 读取text包裹内容
    text = reader.Value;
    reader.Read(); // 读取text末节点
    reader.Read(); // 读取age节点
    reader.Read(); // 读取age包裹内容
    age = int.Parse(reader.Value);
    reader.Read(); // 读取age末节点
}

3. 使用循环读取多个元素

csharp 复制代码
public void ReadXml(XmlReader reader)
{
    // 方法2:使用循环遍历所有元素
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element)
        {
            switch (reader.Name)
            {
                case "text":
                    reader.Read();
                    text = reader.Value;
                    break;
                case "age":
                    reader.Read();
                    age = int.Parse(reader.Value);
                    break;
            }
        }
    }
}

4. 读取包裹节点(复杂反序列化)

csharp 复制代码
public void ReadXml(XmlReader reader)
{
    // 使用XmlSerializer进行复杂类型的反序列化
    XmlSerializer ser3 = new XmlSerializer(typeof(string));
    XmlSerializer ser4 = new XmlSerializer(typeof(int));
    
    reader.Read(); // 跳过根节点
    reader.ReadStartElement();
    text = (string)ser3.Deserialize(reader);
    reader.ReadEndElement();
    
    reader.Read();
    reader.ReadStartElement();
    age = (int)ser4.Deserialize(reader);
    reader.ReadEndElement();
}
3.5.5 完整的IXmlSerializable实现示例

基于您的代码的完整实现:

csharp 复制代码
using UnityEngine;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Collections.Generic;

/// <summary>
/// 自定义XML序列化的数据类
/// 实现IXmlSerializable接口以完全控制XML读写过程
/// </summary>
public class TextData : IXmlSerializable
{
    public string text = "gsffs";
    public int age;
    public List<string> list;
    public int[] array = new int[3] { 1, 2, 3 };
    
    /// <summary>
    /// 返回XML架构定义
    /// </summary>
    /// <returns>通常返回null</returns>
    public XmlSchema GetSchema()
    {
        return null;
    }
    
    /// <summary>
    /// 自定义XML反序列化过程
    /// </summary>
    /// <param name="reader">XML读取器</param>
    public void ReadXml(XmlReader reader)
    {
        // 使用XmlSerializer进行复杂类型的反序列化
        XmlSerializer ser3 = new XmlSerializer(typeof(string));
        XmlSerializer ser4 = new XmlSerializer(typeof(int));
        
        reader.Read(); // 跳过根节点
        reader.ReadStartElement();
        text = (string)ser3.Deserialize(reader);
        reader.ReadEndElement();
        
        reader.Read();
        reader.ReadStartElement();
        age = (int)ser4.Deserialize(reader);
        reader.ReadEndElement();
    }
    
    /// <summary>
    /// 自定义XML序列化过程
    /// </summary>
    /// <param name="writer">XML写入器</param>
    public void WriteXml(XmlWriter writer)
    {
        // 使用XmlSerializer进行复杂类型的序列化
        XmlSerializer ser = new XmlSerializer(typeof(string));
        writer.WriteStartElement("text1");
        ser.Serialize(writer, text);
        writer.WriteEndElement();
        
        XmlSerializer ser2 = new XmlSerializer(typeof(int));
        writer.WriteStartElement("age");
        ser2.Serialize(writer, age);
        writer.WriteEndElement();
    }
}

/// <summary>
/// IXmlSerializable接口测试类
/// 演示如何使用自定义XML序列化
/// </summary>
public class XmlSerilizef : MonoBehaviour
{
    void Start()
    {
        // 设置存储路径
        string path = Application.persistentDataPath + "/TextData.xml";
        print("存储路径: " + path);
        
        // 创建测试数据
        TextData textData = new TextData();
        textData.list = new List<string>() { "1", "2", "3" };
        textData.age = 25;
        
        // 序列化对象到XML文件
        XmlSerializer ser444 = new XmlSerializer(typeof(TextData));
        using (StreamWriter sw = new StreamWriter(path))
        {
            ser444.Serialize(sw, textData);
        }
        
        // 从XML文件反序列化对象
        TextData textData2;
        using (StreamReader sr = new StreamReader(path))
        {
            textData2 = (TextData)ser444.Deserialize(sr);
        }
        
        // 验证反序列化结果
        if (textData2 != null)
        {
            print("反序列化成功!");
            print("文本: " + textData2.text);
            print("年龄: " + textData2.age);
        }
    }
}
3.5.6 IXmlSerializable接口的优势和应用场景

优势:

  1. 完全控制:可以完全控制XML的读写过程
  2. 灵活性:支持复杂的XML结构和自定义格式
  3. 性能优化:可以针对特定需求优化序列化性能
  4. 兼容性:可以处理不同版本的XML格式

应用场景:

  1. 复杂数据结构:当默认序列化无法处理复杂的数据结构时
  2. 自定义格式:需要生成特定格式的XML时
  3. 性能要求:对序列化性能有特殊要求时
  4. 版本兼容:需要处理不同版本的XML格式时
3.5.7 注意事项和最佳实践

1. 实现要求

csharp 复制代码
// 必须实现所有三个方法
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader) { /* 自定义读取逻辑 */ }
public void WriteXml(XmlWriter writer) { /* 自定义写入逻辑 */ }

2. 错误处理

csharp 复制代码
public void ReadXml(XmlReader reader)
{
    try
    {
        // 自定义读取逻辑
        reader.Read();
        text = reader.Value;
    }
    catch (System.Exception e)
    {
        Debug.LogError("XML读取失败: " + e.Message);
    }
}

通过实现 IXmlSerializable 接口,可以为Unity项目提供高度自定义的XML序列化解决方案,特别适合需要精确控制XML格式的复杂应用场景。

相关推荐
霜绛39 分钟前
Unity笔记(六)——Mathf、三角函数、坐标系、向量
笔记·学习·unity·游戏引擎
SmalBox1 小时前
【渲染流水线】[逐片元阶段]-[混合Blend]以UnityURP为例
unity·渲染
专注VB编程开发20年1 小时前
对excel xlsx文件格式当成压缩包ZIP添加新的目录和文件后,OpenXml、NPOI、EPPlus、Spire.Office组件还能读出来吗
数据库·c#·excel
俊昭喜喜里2 小时前
C#和SQL Server Management Studio的连接
服务器·数据库·c#
时光追逐者2 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 51 期(2025年8.18-8.24)
c#·.net·.netcore·.net core
DanmF--2 小时前
Unity中的特殊文件夹
unity·c#·游戏引擎
野区捕龙为宠4 小时前
Unity Netcode for GameObjects(多人联机小Demo)
java·unity·游戏引擎
程序设计实验室5 小时前
上位机开发之假装有设备,使用 C# 模拟串口设备
c#·上位机
CodeCraft Studio16 小时前
3D文档控件Aspose.3D实用教程:使用 C# 构建 OBJ 到 U3D 转换器
开发语言·3d·c#·3d渲染·aspose·3d文件格式转换·3d sdk
相信神话202116 小时前
Godot Shader 中 mix 函数的用法
游戏引擎·godot