You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用序列化特性将固定ID的XML列表反序列化为指定C#类?

问题描述

给定以下XML:

<Values>
  <Value ID="Foo">foo</Value>
  <Value ID="Bar">42</Value>
</Values>

已知ID列表固定不变,请问如何使用序列化特性将其解析为如下C#类?

public class Values {
    public string Foo { get; set; }
    public int Bar { get; set; }
}

直接解析为数组的方法虽然简单,但验证和读取值时非常繁琐,当前实现代码如下:

[Serializable]
public class Values
{
    [XmlElement("Values")]
    public Value[]? Values { get; init; }
}

[Serializable]
public class Value
{
    [XmlAttribute("ID")]
    public string? Id { get; init; }

    [XmlText]
    public string? Value { get; init; }
}
解决方案

可以通过实现IXmlSerializable接口自定义序列化和反序列化逻辑,直接将XML中的Value元素按ID映射到目标类的属性上,具体实现如下:

using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

public class Values : IXmlSerializable
{
    public string Foo { get; set; } = string.Empty;
    public int Bar { get; set; }

    public XmlSchema? GetSchema() => null;

    public void ReadXml(XmlReader reader)
    {
        // 跳过根元素开始标签
        reader.ReadStartElement("Values");

        while (reader.NodeType != XmlNodeType.EndElement)
        {
            if (reader.Name == "Value")
            {
                var id = reader.GetAttribute("ID");
                var valueContent = reader.ReadElementContentAsString();

                switch (id)
                {
                    case "Foo":
                        Foo = valueContent;
                        break;
                    case "Bar":
                        if (int.TryParse(valueContent, out var barVal))
                        {
                            Bar = barVal;
                        }
                        break;
                }
            }
            else
            {
                // 跳过未知节点
                reader.Skip();
            }
        }

        // 读取根元素结束标签
        reader.ReadEndElement();
    }

    public void WriteXml(XmlWriter writer)
    {
        // 生成Foo对应的Value元素
        writer.WriteStartElement("Value");
        writer.WriteAttributeString("ID", "Foo");
        writer.WriteString(Foo);
        writer.WriteEndElement();

        // 生成Bar对应的Value元素
        writer.WriteStartElement("Value");
        writer.WriteAttributeString("ID", "Bar");
        writer.WriteString(Bar.ToString());
        writer.WriteEndElement();
    }
}

使用示例

// 反序列化示例
var xmlContent = @"<Values>
  <Value ID=""Foo"">foo</Value>
  <Value ID=""Bar"">42</Value>
</Values>";

var serializer = new XmlSerializer(typeof(Values));
using var reader = new StringReader(xmlContent);
var valuesObj = (Values)serializer.Deserialize(reader)!;

Console.WriteLine(valuesObj.Foo); // 输出: foo
Console.WriteLine(valuesObj.Bar); // 输出: 42

// 序列化示例
var newValues = new Values { Foo = "newFoo", Bar = 100 };
using var writer = new StringWriter();
serializer.Serialize(writer, newValues);
Console.WriteLine(writer.ToString());
// 输出符合原格式的XML

这种方式完全自定义了序列化逻辑,既满足了XML到目标类的映射需求,又避免了数组方式的繁琐操作,且因ID固定,逻辑清晰易维护。


内容的提问来源于stack exchange,提问作者Jakube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:32:48