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

C#如何反序列化按属性区分的同名XML元素并映射到指定类属性

答案

结论

该需求完全可以实现,不需要强制实现IXmlSerializable接口,有两种常用实现方案可选:


方案1:中间列表属性映射(推荐,无需自定义序列化逻辑)

你可以先在类中增加一个接收所有ConstructionDepotBalance元素的列表属性,反序列化完成后自动根据contextRef过滤取值到期初/期末属性即可,改动量极小且易维护。

首先定义辅助类接收Balance元素的属性和值:

public class ConstructionDepotBalance
{
    [XmlAttribute("contextRef")]
    public string ContextRef { get; set; }
    [XmlText]
    public long Value { get; set; }
}

修改ConstructionDepotSpecification类实现自动映射:

public partial class ConstructionDepotSpecification 
{
    public string ConstructionDepotLabel { get; set; }

    // 反序列化时自动填充所有ConstructionDepotBalance节点
    [XmlElement("ConstructionDepotBalance")]
    public List<ConstructionDepotBalance> BalanceList { get; set; }

    // 标记XmlIgnore避免序列化时重复输出,自动从列表过滤对应值
    [XmlIgnore]
    public long? ConstructionDepotBalanceBegin 
    { 
        get => BalanceList?.FirstOrDefault(b => b.ContextRef == "Context_Instant_Begin")?.Value; 
    }

    [XmlIgnore]
    public long? ConstructionDepotBalanceEnd 
    { 
        get => BalanceList?.FirstOrDefault(b => b.ContextRef == "Context_Instant_End")?.Value; 
    }
}

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

如果不想增加额外的辅助类和中间属性,也可以通过实现IXmlSerializable完全自定义反序列化流程,直接把值写入目标属性:

public partial class ConstructionDepotSpecification : IXmlSerializable
{
    public string ConstructionDepotLabel { get; set; }
    public long? ConstructionDepotBalanceBegin { get; set; }
    public long? ConstructionDepotBalanceEnd { get; set; }

    public XmlSchema GetSchema() => null;

    public void ReadXml(XmlReader reader)
    {
        reader.ReadStartElement();
        while (reader.NodeType != XmlNodeType.EndElement)
        {
            if (reader.Name == nameof(ConstructionDepotLabel))
            {
                ConstructionDepotLabel = reader.ReadElementContentAsString();
            }
            else if (reader.Name == "ConstructionDepotBalance")
            {
                var contextRef = reader.GetAttribute("contextRef");
                var value = reader.ReadElementContentAsLong();
                if (contextRef == "Context_Instant_Begin")
                    ConstructionDepotBalanceBegin = value;
                else if (contextRef == "Context_Instant_End")
                    ConstructionDepotBalanceEnd = value;
            }
            else
            {
                reader.Skip();
            }
        }
        reader.ReadEndElement();
    }

    public void WriteXml(XmlWriter writer)
    {
        // 需要序列化回XML时可在此实现对应逻辑,无需求可留空
        throw new NotImplementedException();
    }
}

该方案的特点是完全控制序列化/反序列化逻辑,不需要额外辅助类,但后续字段新增时需要手动修改ReadXml方法适配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 01:54:02