如何继承XmlElement实现特定XML节点的自定义表示类?有哪些最佳方案?
解决方案
方案1:使用组合代替继承(更推荐)
不要继承XmlElement,改为在自定义类中封装XmlElement实例,从根源上避免父类实例无法转换为子类实例的限制:
class CDataObject { // 内部封装原生XmlElement实例 private readonly XmlElement _element; // 构造函数直接接收查询得到的XmlElement public CDataObject(XmlElement element) { // 可加节点合法性校验 if (element.LocalName != "Obj") throw new ArgumentException("节点类型不匹配"); _element = element; } // 封装你需要的节点属性 public string Class => _element.GetAttribute("class"); public string Dist => _element.GetAttribute("dist"); // 封装parameter节点访问方法 public string GetParameter(string paramName) { var paramNode = _element.SelectSingleNode($"parameter[@name='{paramName}']"); return paramNode?.InnerText ?? string.Empty; } // 调整查询方法逻辑 public static CDataObject FindObject(XmlDocument doc, string objClass, string objDist) { string xpath = $"//Obj[@class='{objClass}' and @dist='{objDist}']"; XmlElement targetNode = doc.DocumentElement.SelectSingleNode(xpath) as XmlElement; return targetNode == null ? null : new CDataObject(targetNode); } }
该方案不需要修改XML加载逻辑,兼容性强,后续扩展自定义方法也更灵活。
方案2:重写XmlDocument的节点创建逻辑(适合必须继承XmlElement的场景)
默认XmlDocument加载XML时生成的都是原生XmlElement实例,因此你查询到的节点自然无法转换为自定义子类。你已经实现了自定义的XmlDocument子类,只需要重写其CreateElement方法,让它碰到<Obj>节点时返回你自定义的CDataObject实例即可:
// 你已有的自定义XmlDocument类 class CustomXmlDocument : XmlDocument { public override XmlElement CreateElement(string prefix, string localName, string namespaceURI) { // 碰到Obj节点就返回自定义类实例 if (localName == "Obj") { return new CDataObject(prefix, localName, namespaceURI, this); } return base.CreateElement(prefix, localName, namespaceURI); } }
后续所有XML操作都使用CustomXmlDocument实例加载、处理文件,此时文档中所有<Obj>节点原生就是CDataObject类型,你原来的类型转换逻辑可以直接生效。
内容的提问来源于stack exchange,提问作者RageLog
相关产品推荐
相关产品推荐

