如何让XmlSerialize/XmlDeserialize识别ValueTuple的命名?
XmlSerializer如何支持ValueTuple的命名序列化与反序列化?
XmlSerializer默认不支持ValueTuple的命名元素,这是因为命名元组的x、y只是编译期的语法糖,运行时元组的底层字段仍然是Item1、Item2,序列化器只会识别这些底层字段名称,所以默认输出的XML会用Item1、Item2作为元素名。手动修改XML为x、y后反序列化失败,是因为序列化器找不到对应的Item1/Item2字段,会直接使用元组的默认值(0,0),且默认不会抛出错误。
要实现用自定义名称序列化/反序列化ValueTuple,可以用以下两种方法:
方法一:使用代理属性(推荐,实现简单)
把原ValueTuple字段设为私有,通过一个可序列化的代理类作为属性,来映射自定义名称的XML元素:
public class MyClass { // 私有元组字段,不参与序列化 private (int x, int y) _coord; // 供XmlSerializer序列化的代理属性 [XmlElement("coord")] public CoordProxy Coord { get => new CoordProxy { X = _coord.x, Y = _coord.y }; set => _coord = (value.X, value.Y); } // 对外保留元组访问的属性(可选) public (int x, int y) CoordTuple { get => _coord; set => _coord = value; } // 用于序列化的代理类 public class CoordProxy { [XmlElement("x")] public int X { get; set; } [XmlElement("y")] public int Y { get; set; } } }
序列化后得到的XML结构:
<coord> <x>1</x> <y>2</y> </coord>
方法二:实现IXmlSerializable接口(灵活度更高)
通过自定义序列化/反序列化逻辑,直接控制XML的生成和解析:
public class MyClass : IXmlSerializable { public (int x, int y) coord; public XmlSchema GetSchema() => null; public void ReadXml(XmlReader reader) { // 读取外层coord元素 reader.ReadStartElement("coord"); // 读取自定义名称的x、y元素 int x = int.Parse(reader.ReadElementString("x")); int y = int.Parse(reader.ReadElementString("y")); coord = (x, y); reader.ReadEndElement(); } public void WriteXml(XmlWriter writer) { // 写入外层coord元素 writer.WriteStartElement("coord"); // 写入自定义名称的x、y元素 writer.WriteElementString("x", coord.x.ToString()); writer.WriteElementString("y", coord.y.ToString()); writer.WriteEndElement(); } }
这种方式序列化后的XML会完全符合预期结构,反序列化时也能正确识别x、y元素。
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

