当前位置: 首页 > ops >正文

Unity_数据持久化_IXmlSerializable接口

Unity数据持久化

三、XML数据持久化

3.5 IXmlSerializable接口

3.5.1 IXmlSerializable接口基础概念

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

接口定义:

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接口

基本实现结构:

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)

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

生成的XML格式:

<TextData text="gsffs" age="25" />

2. 写入元素节点(Element)

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

生成的XML格式:

<TextData><text>gsffs</text><age>25</age>
</TextData>

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

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格式:

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

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

1. 读取属性(Attribute)

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

2. 读取元素节点(Element)

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. 使用循环读取多个元素

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. 读取包裹节点(复杂反序列化)

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实现示例

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

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. 实现要求

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

2. 错误处理

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

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

http://www.xdnf.cn/news/16896.html

相关文章:

  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘scikit-learn’问题
  • ESP32学习-I2C(IIC)通信详解与实践
  • Azure DevOps — Kubernetes 上的自托管代理 — 第3部分
  • GB 44496-2024《汽车软件升级通用技术要求》对行业从业者的变革性影响
  • 13-day10生成式任务
  • 从Docker衔接到导入黑马商城以及前端登录显示用户或密码错误的相关总结(个人理解,仅供参考)
  • 【AI编程工具IDE/CLI/插件专栏】-国外IDE与Cursor能力对比
  • 【openlayers框架学习】九:openlayers中的交互类(select和draw)
  • 【LLM】 BaseModel的作用
  • MySQL面试题及详细答案 155道(021-040)
  • Spring Cloud微服务中的内存泄漏问题定位与解决方案
  • SelectDB数据库,新一代实时数据仓库的全面解析与应用
  • Linux 环境下 Docker 安装与简单使用指南
  • 百度招黑产溯源安全工程师
  • 《软件测试与质量控制》实验报告二 单元测试
  • MSQL-聚簇索引与非聚簇索引的比较
  • Python编程基础与实践:Python文件处理入门
  • SpringBoot 信用卡检测、OpenAI gym、OCR结合、DICOM图形处理、知识图谱、农业害虫识别实战
  • 【7.5 Unity AssetPostprocessor】
  • 【自动化运维神器Ansible】YAML支持的数据类型详解:构建高效Playbook的基石
  • linux ext4缩容home,扩容根目录
  • Trae + Notion MCP:将你的Notion数据库升级为智能对话机器人
  • 元宇宙重构未来交通新图景
  • 无人机光伏巡检漏检率↓78%!陌讯多模态融合算法实战解析
  • 机试备考笔记 2/31
  • Agentic RAG:自主检索增强生成的范式演进与技术突破
  • 深入 Go 底层原理(二):Channel 的实现剖析
  • 深入 Go 底层原理(十四):timer 的实现与高性能定时器
  • cuda编程笔记(12)--学习cuFFT的简单使用
  • 【机器学习】非线性分类算法(上):KNN(基于距离相似度)与朴素(特征独立)贝叶斯(基于概率统计)