【问题标题】:XmlSerializer bug when serializing collection of collections without root element?序列化没有根元素的集合时出现 XmlSerializer 错误?
【发布时间】:2010-01-18 11:38:54
【问题描述】:

这是一个有点长的问题,但我已经尽可能简洁了,所以请多多包涵。在我看来,这就像 XmlSerializer 类中的一个错误,但在我将它提交给 Microsoft 之前,我想看看我是否遗漏了什么,这是完全可能的。

我正在尝试生成以下 XML 作为代表性案例,它本质上是集合的集合,但外部集合具有附加元素:

<Links>
  <Name />
  <Group>
    <Link />
    <Link />
  </Group>
  <Group>
    <Link />
    <Link />
  </Group>
</Links>

序列化类如下:

public class Link { }

public class Links
{
    public string Name { get; set; }

    [XmlElement("Group")]
    public Link[][] Groups { get; set; }
}

运行它的简单测试程序如下:

class Program
{
    static void Main()
    {
        var serializer = new XmlSerializer(typeof(Links));
        var links = new Links { Name = "", Groups = new[] { 
            new[] { new Link(), new Link() }, 
            new[] { new Link(), new Link() } } };
        serializer.Serialize(Console.Out, links);
    }
}

这使用了using XmlElement to remove the parent node of the collection 的技巧,这意味着不会发出&lt;Groups&gt; 元素,并且对于包含在外部数组(类型为Link[])中的每个对象,&lt;Group&gt; 元素应该是发出。但是,在运行时,XmlSerializer 会出现以下异常:

无法生成临时类(结果=1)。 错误 CS0030:无法将类型“Link[][]”转换为“Link[]” 错误 CS0029:无法将类型“Link[]”隐式转换为“Link[][]”

我的猜测是序列化程序出于某种原因试图展平集合,并认为外部数组中包含的类型是Link而不是Link[],这导致其序列化类作为类型的编译失败不匹配。

你怎么看?这是一个错误吗?在使用XmlSerializer 之后,是否有一种解决方法可以生成我正在使用的 XML?

【问题讨论】:

    标签: .net collections xmlserializer


    【解决方案1】:

    我可以使用 XmlArrayItem 属性获得几乎相同的结构:

    [XmlArrayItem(ElementName = "Group", Type = typeof(Link[]))]
    Link[][] Groups;
    

    但我仍然得到一个顶级组元素。至少锯齿状数组的序列化是这样工作的。

    就我的测试而言,没有办法让 XmlElement 属性与锯齿状数组一起使用。我不确定这是错误还是“功能”。我同意,从错误消息来看,这看起来像是一个错误。至少它应该抛出具有锯齿状数组属性的 XmlElement 不受支持,而不是尝试将 [] 放入 [][] 时失败。

    【讨论】:

    • 是的,我也试过[XmlArrayItem],在这里它确实正确地识别出包含的类型是Link[]而不是Link,这让我相信它可能是一个错误(虽然有点难说,因为[XmlElement] 在集合展平方面的行为在我能看到的任何地方都没有完全指定)。我会等一下,看看是否有其他人发布任何可以更清楚地说明它的东西,但看来你已经证实了我的怀疑。
    【解决方案2】:

    我建议编写一个 XML 模式,它定义您希望在 XML 中具有的语法,然后使用代码生成工具(例如 MS xsd.exe)从中生成相应的序列化代码。 无论如何,编写模式是一种很好的数据验证方法。就算以后不想用,想自己维护代码,也至少可以看看生成的代码。

    【讨论】:

    • 我已经尝试过了...生成的代码看起来与问题中的完全一样,然后在运行时失败...
    • 那么我还是建议给 MS 写一个错误报告,因为他们的 XSD.exe 工具正在生成无法工作的代码。
    【解决方案3】:

    就我所见,问题正是错误所在。

    您为尝试序列化的类编写所需的 XML 的方式表明 Group 是链接的集合;然而,它被定义为一个锯齿状的链接数组(即一个数组数组)。

    相信你把它还原成一个简单的数组,问题就解决了。


    编辑添加

    如果你真的需要你指定的 XML,你可以实现 IXmlSerializable 接口并自己创建和读取 XML。

    当事情没有按我们预期的方式工作时,它总是一个解决方案。

    【讨论】:

    • 如果我将它还原为一个简单的数组,那么它将不是一个集合的集合,它只是一个集合,并且只有一个 Group 元素,而不是多个元素。 Groups 属性包含 多个 组,而不是一个。
    • 然后我将群组设为List&lt;Link[]&gt;
    • List&lt;Link[]&gt; 没有解决它。您只会得到另一个名为 ArrayOfLink 的“组”,因为您无法指定应该调用哪些内部元素(列表的项目)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 2012-07-25
    • 2014-10-06
    • 2011-06-14
    • 2016-07-16
    • 1970-01-01
    相关资源
    最近更新 更多