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
相关产品推荐
相关产品推荐

