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格式的复杂应用场景。

相关推荐
lihongli0004 小时前
消息系统技术文档
网络·unity·游戏引擎
格林威4 小时前
Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现路口车辆速度的追踪识别(C#代码UI界面版)
人工智能·深度学习·数码相机·yolo·计算机视觉·c#·视觉检测
CodeCraft Studio4 小时前
国产化Word处理控件Spire.Doc教程:Python提取Word文档中的文本、图片、表格等
python·c#·word·国产化·spire.doc·word文档处理·文档开发控件
Kookoos5 小时前
ABP VNext + Quartz.NET vs Hangfire:灵活调度与任务管理
c#·.net·hangfire·quartz.net·abp vnext
LZQqqqqo7 小时前
C# 事件Event
开发语言·c#
时光追逐者8 小时前
C#/.NET/.NET Core优秀项目和框架2025年7月简报
c#·.net·.netcore
Edision_li8 小时前
基于Mediapipe_Unity_Plugin实现手势识别
unity·游戏引擎·unity 手势识别
与火星的孩子对话9 小时前
Unity Shader编程完全入门指南:从零到实战 C# 实战案例
unity·c#·游戏引擎
谷宇.9 小时前
【Unity3D实例-功能-镜头】第三人称视觉
游戏·unity·unity3d·游戏开发·游戏编程·steam