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

XML序列化/反序列化:如何为同一类不同实例的属性设置不同别名

实现方案

有两种稳定可行的实现方式,无需自定义完整的XmlSerializer,使用.NET XML序列化框架原生能力即可满足需求:

方案1:代理属性适配(轻量无侵入)

通过新增序列化专用代理属性+DTO的方式实现,不改动原有业务逻辑,代码易维护:

步骤1:新增DataB场景下的ClassA适配类

public class ClassADtoForDataB
{
    [XmlElement("Name")]
    public string Code { get; set; }
    [XmlElement("Text")]
    public string Value { get; set; }

    // 隐式转换实现与原ClassA的无缝互转
    public static implicit operator ClassADtoForDataB(ClassA source)
    {
        return new ClassADtoForDataB { Code = source.Code, Value = source.Value };
    }

    public static implicit operator ClassA(ClassADtoForDataB source)
    {
        return new ClassA { Code = source.Code, Value = source.Value };
    }
}

步骤2:修改Foo类的序列化配置

public class Foo
{
    // 原业务属性标记为忽略序列化
    [XmlIgnore]
    public List<ClassA> DataA { get; set; }
    [XmlIgnore]
    public List<ClassA> DataB { get; set; }

    // 序列化专用属性
    [XmlArray("DataA")]
    [XmlArrayItem("ClassA")]
    public List<ClassA> SerializeDataA
    {
        get => DataA;
        set => DataA = value;
    }

    [XmlArray("DataB")]
    [XmlArrayItem("ClassA")]
    public List<ClassADtoForDataB> SerializeDataB
    {
        get => DataB?.Select(x => (ClassADtoForDataB)x).ToList();
        set => DataB = value?.Select(x => (ClassA)x).ToList();
    }
}

方案2:实现IXmlSerializable接口(完全自定义序列化逻辑)

如果不希望新增额外类,可直接让Foo类实现IXmlSerializable接口,自主控制序列化/反序列化的全流程,输出XML完全符合预期:

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

public class Foo : IXmlSerializable
{
    public List<ClassA> DataA { get; set; }
    public List<ClassA> DataB { get; set; }

    public XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader)
    {
        reader.ReadStartElement(nameof(Foo));
        
        // 反序列化DataA节点
        reader.ReadStartElement(nameof(DataA));
        DataA = new List<ClassA>();
        while (reader.NodeType == XmlNodeType.Element && reader.Name == nameof(ClassA))
        {
            var item = new ClassA();
            reader.ReadStartElement(nameof(ClassA));
            item.Code = reader.ReadElementContentAsString(nameof(Code), string.Empty);
            item.Value = reader.ReadElementContentAsString(nameof(Value), string.Empty);
            reader.ReadEndElement();
            DataA.Add(item);
        }
        reader.ReadEndElement();

        // 反序列化DataB节点
        reader.ReadStartElement(nameof(DataB));
        DataB = new List<ClassA>();
        while (reader.NodeType == XmlNodeType.Element && reader.Name == nameof(ClassA))
        {
            var item = new ClassA();
            reader.ReadStartElement(nameof(ClassA));
            item.Code = reader.ReadElementContentAsString("Name", string.Empty);
            item.Value = reader.ReadElementContentAsString("Text", string.Empty);
            reader.ReadEndElement();
            DataB.Add(item);
        }
        reader.ReadEndElement();

        reader.ReadEndElement();
    }

    public void WriteXml(XmlWriter writer)
    {
        // 序列化DataA节点
        writer.WriteStartElement(nameof(DataA));
        foreach (var item in DataA ?? Enumerable.Empty<ClassA>())
        {
            writer.WriteStartElement(nameof(ClassA));
            writer.WriteElementString(nameof(Code), item.Code);
            writer.WriteElementString(nameof(Value), item.Value);
            writer.WriteEndElement();
        }
        writer.WriteEndElement();

        // 序列化DataB节点
        writer.WriteStartElement(nameof(DataB));
        foreach (var item in DataB ?? Enumerable.Empty<ClassA>())
        {
            writer.WriteStartElement(nameof(ClassA));
            writer.WriteElementString("Name", item.Code);
            writer.WriteElementString("Text", item.Value);
            writer.WriteEndElement();
        }
        writer.WriteEndElement();
    }
}

说明

XmlAttributeOverrides无法实现该需求的原因是其配置是针对类型全局生效的,无法为同一个类型在不同父级属性下配置不同的映射规则,上述两种方案都可以完美规避这个问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 02:24:04