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接口的优势和应用场景
优势:
- 完全控制:可以完全控制XML的读写过程
- 灵活性:支持复杂的XML结构和自定义格式
- 性能优化:可以针对特定需求优化序列化性能
- 兼容性:可以处理不同版本的XML格式
应用场景:
- 复杂数据结构:当默认序列化无法处理复杂的数据结构时
- 自定义格式:需要生成特定格式的XML时
- 性能要求:对序列化性能有特殊要求时
- 版本兼容:需要处理不同版本的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格式的复杂应用场景。