c# - 在 .NET XML 反序列化中,如何允许数组类型的多态使用?

标签 c# .net xml xml-serialization xsd

示例架构:

<complexType name="Dog">...</complexType>
<complexType name="Cat">...</complexType>

<complexType name="ArrayOfDog">
    <sequence>
        <element name="Dog" type="tns:Dog minOccurs="0" maxOccurs="unbounded" />
    </sequence>
</complexType>

<complexType name="Foo">
    <sequence>
        <element name="Bar" type="string"/>          
        <element name="Baz" type="anyType"/>
    </sequence>
</complexType>

通过 .NET 的 wsdl.exe 运行它会生成类似于以下的代码:

[System.Xml.Serialization.XmlIncludeAttribute(typeof(Dog[]))]

public partial class Dog { ... }

public partial class Cat { ... }

public partial class Foo {
    private string barField;
    private object bazField;
}

看起来 wsdl.exe 试图变得“聪明”并意识到我的 ArrayOfDog 实际上只是一个可以编码为 C# 数组的包装器类型。当在另一种数据类型中显式引用 ArrayOfDog 时,这可以正常工作。但是,当以多态方式使用 ArrayOfDog 时(例如,作为 xsd:anyType 的替代),这会中断。它似乎中断了,因为 .NET 运行时对名为“ArrayOfDog”的复杂类型一无所知 - 它基本上丢弃了此信息,转而使用 native C# 数组。

示例 XML 文档 1:

<Foo>
    <Bar>Hello</Bar>
    <Baz xsi:type="Cat">
        ...
    </Baz>
</Foo>

示例 XML 文档 2:

<Foo>
    <Bar>Hello</Bar>
    <Baz xsi:type="ArrayOfDog">
        <Dog>...</Dog>
        <Dog>...</Dog>
    </Baz>
</Foo>

文档 #1 已被运行时正确反序列化。我得到一个 Foo 类型的对象,其中包含正确反序列化的 Bar 和 Baz 字段。

文档 #2 被运行时错误地反序列化。我得到了一个 Foo 类型的对象,它具有正确反序列化的 Bar 字段,但是对于 Baz 字段,我得到了 System.XML.XMLNode[]。我的猜测是因为运行时对名为“ArrayOfDog”的实体的任何类型绑定(bind)一无所知。您可能认为 XmlInclude 指令“XmlIncludeAttribute(typeof(Dog[]))”会处理这个问题,但它似乎不起作用。

有没有人遇到过这个?

这里有优雅的解决方案吗?我正在考虑使用的解决方法是将我的“ArrayOf”类型包装在另一种类型中,并将其包含在 xsd:anyType 的替换中。

最佳答案

我不认为这与多态性有任何关系。我认为这是 XML 序列化程序中的一个错误,假设任何名为“ArrayOfDog”的类型包含一个“Dog”序列是为了表示一个 Dog[]。作为对该理论的测试,尝试将 WSDL 更改为使用名称“BunchOfDogs”,看看这是否会更改客户端中的代理代码。

如果您想在 XML 中实现多态性,那么 ArrayOfDog 和 Cat 都需要是相同基类型的扩展(xsd:any 除外)。如果真是这样,那么我希望 .NET 将 Baz 生成为基本类型。

带有 xsd:any 的模式通常会导致问题。那里几乎可以有任何东西,有些组合根本就没有意义。

您还没有说这个 Java 服务是否来自 Axis,或者它是什么版本。我已经看到 Axis 的行为就好像 xsi:type 是有效模式的替代品。小心需要“正确”使用 xsi:type 的模式。

关于c# - 在 .NET XML 反序列化中,如何允许数组类型的多态使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1007626/

相关文章:

c# - 如何为我们在服务器上开发和运行的应用程序配置 log4net?

c# - 如何在我的项目中实现 WCF?

c# - MSDN 图表实时更改点值?

c# - Substring() 用法混淆

c# - .Net 4 导致 DLLImport 函数返回失败代码,.Net 2、3 或 3.5 不会

c# - automapper - 如何映射对象列表

ruby - 如何使用 Nokogiri 选择元素

android - 如何在 layer-list android 中缩放和居中可绘制对象?

xml - JAXB 是否可以首先通过包含进行编码(marshal),然后通过 @XmlIDREF 进行编码(marshal)以供后续引用?

c# - 编译Release和Debug是不是要生成不同的IL代码+不同的机器码?