C# XmlSerializer反序列化时XmlElementAttribute参数适用场景疑问
XmlElementAttribute传参差异原因及使用规则
首先明确XmlElementAttribute的两类核心重载的作用:
- 传入
string类型参数:用于指定C#属性对应的XML节点名称,解决名称映射问题 - 传入
Type类型参数:用于指定该属性允许序列化/反序列化的具体类型,解决多态派生类的识别问题
场景1差异原因
场景1中集合属性的泛型类型已经是明确的Slide类,XmlSerializer默认就可以识别子项类型,此时需要解决的是名称不匹配问题:
- C#属性名为
Slides(复数),XML中的子节点名为Slide(单数) - 传入
nameof(Slide)等价于传入字符串"Slide",明确告诉序列化器集合子项对应的XML节点名是Slide,和实际XML结构匹配,因此反序列化成功 - 如果替换为
typeof(Slide),走的是传类型的重载,序列化器会默认使用C#属性名Slides作为匹配的节点名,XML中不存在Slides节点,因此匹配失败
对应代码参考:
public class Presentation { // 明确指定子节点名称为Slide,匹配XML结构 [XmlElement(nameof(Slide))] public List<Slide> Slides { get; set; } }
对应XML结构:
<Presentation> <Slide>...</Slide> </Presentation>
场景2差异原因
场景2中集合属性的泛型类型是基类Shape,XmlSerializer默认只能识别基类,不知道存在TextBox、Table等派生类,此时需要解决的是多态类型识别问题:
- 传入
typeof(TextBox)、typeof(Table),明确告诉序列化器该集合允许放入这两个派生类,同时序列化器会默认使用类名作为对应的XML节点名,刚好和XML中的TextBox、Table节点匹配,因此反序列化成功 - 如果替换为
nameof(TextBox),走的是传名称的重载,序列化器还是不知道集合可以容纳派生类,只会按照基类Shape反序列化,无法匹配派生类结构,因此报错或返回空结果
对应代码参考:
public class Slide { // 明确指定集合允许的派生类型,默认用类名匹配XML节点 [XmlElement(typeof(TextBox))] [XmlElement(typeof(Table))] public List<Shape> Shapes { get; set; } }
对应XML结构:
<Slide> <TextBox>...</TextBox> <Table>...</Table> </Slide>
通用使用规则
- 当C#属性名和XML节点名不一致,或者集合子项的节点名和属性名不一致时,传字符串参数指定节点名,推荐用
nameof保证名称同步 - 当属性/集合的声明类型是基类/接口,需要支持派生类序列化/反序列化时,传
Type参数指定允许的派生类型 - 如果需要同时指定自定义节点名和派生类型,可以同时传两个参数,示例:
[XmlElement("CustomTextNode", typeof(TextBox))],此时XML节点名为CustomTextNode时会被反序列化为TextBox类型
内容的提问来源于stack exchange,提问作者Swanand
相关产品推荐
相关产品推荐

