System.Xml.Serialization 中作为 XmlElementAttribute 参数的元素名称或类型

Element name or type as argument to XmlElementAttribute in System.Xml.Serialization

同时使用XmlSerializer反序列化

案例一: Presentation 包含 Slide

类型的子元素
<Presentation>
    <Slide>
        ...
    </Slide>
</Presentation>

nameof 获取正确的结果,即 elementName 应该通过。将其替换为 typeof 会给出不正确的结果。

public class Presentation
{
    ...
    [XmlElement(nameof(Slide))]
    public List<Slide> Slides { get; set; }
    ...
}

案例二: Slide 包含派生自基础 class Shape

TextBoxTable 类型的子元素
<Slide>
    <TextBox>
        ...
    </TextBox>
    <Table>
        ...
    </Table>
</Slide>

typeof 获取正确的结果,即 type 应该通过。将其替换为 nameof 会给出不正确的结果。

public class Slide
{
    ...
    [XmlElement(typeof(TextBox))]
    [XmlElement(typeof(Table))]
    public List<Shape> Shapes { get; set; }
    ...
}

谁能解释一下上面的内容?什么时候提供元素名称,什么时候提供类型?

基于 C# 属性,XmlSerializer 构造函数通过使用反射分析 类 生成一对 XmlSerializationReaderXmlSerializationWriter 派生的 类 [1]. A mapping between the element names in the XML and types in C# is then also established[2].

XmlElementAttribute(string elementName, Type type)用于集合时,每个属性对应一个这样的映射。这取决于每个属性的以下逻辑

  • 不指定type时,根据集合中元素的类型推断

  • 如果指定一个属性或不指定属性(相同类型对象的集合)

    • 未指定名称时,从属性
    • 的名称推断
  • 如果指定了两个或多个属性(不同类型对象的集合)

    • 未指定名称时,根据提供给属性或由属性推断的类型的名称推断

这在 documentation of XmlAttribute

中也有说明

Note that when you apply the XmlElementAttribute multiple times without specifying an ElementName property value, the elements are named after the type of the acceptable objects.

现在参考OP,

案例一:

[XmlElement(nameof(Slide))]

类似于

[XmlElement("Slide", typeof(Slide))]

将其替换为 typeof 将类似于

[XmlElement("Slides", typeof(Slide))]

这意味着我们需要将 "Slides" 指定为 XML 中的元素名称而不是 "Slide",因此结果不正确。

案例二:

[XmlElement(typeof(TextBox))]
[XmlElement(typeof(Table))]

类似于

[XmlElement("TextBox", typeof(TextBox))]
[XmlElement("Table", typeof(Table))]

将其替换为 nameof 将类似于

[XmlElement("TextBox", typeof(Shape))]
[XmlElement("Table", typeof(Shape))]

此处,在 TextBoxTable 之间,对于类型 Shape 的映射内容存在歧义。因此,映射本身无法建立,代码退出。