5

我看过很多关于 .NET 3.5 SP1 更改的帖子,但偶然发现了一篇我昨天还没有看到文档的帖子。我的代码在我的机器上运行良好,从 VS、msbuild 命令行,一切,但它在构建服务器上失败了(运行 .NET 3.5 RTM)。

[XmlRoot("foo")]
public class Foo
{
    static void Main()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Foo));

        string xml = @"<foo name='ack' />";
        using (StringReader sr = new StringReader(xml))
        {
            Foo foo = serializer.Deserialize(sr) as Foo;
        }
    }

    [XmlAttribute("name")]
    public string Name { get; set; }

    public Foo Bar { get; private set; }
}

在 SP1 中,上面的代码运行得很好。在 RTM 中,您会收到 InvalidOperationException:

无法生成临时类(结果=1)。错误 CS0200:无法将属性或索引器“ConsoleApplication2.Foo.Bar”分配给 -- 它是只读的

当然,让它在 RTM 下运行所需的只是将 [XmlIgnore] 添加到 Bar 属性。

我的 google fu 显然无法找到此类更改的文档。是否有任何地方的更改列表列出了此更改(以及类似的可能会跳起来并大喊“gotcha”的引擎盖下的更改)?这是错误还是功能?

编辑:在 SP1 中,如果我添加了一个<Bar />元素,或者为 Bar 属性设置了 [XmlElement],它不会被反序列化。它在尝试反序列化时不会在 SP1 之前失败 - 在构造 XmlSerializer 时会引发异常。

这让我更倾向于认为它是一个错误,特别是如果我为 Foo.Bar 设置了 [XmlElement] 属性。如果它不能做我要求它做的事情,它应该抛出一个异常而不是默默地忽略 Foo.Bar。XML 序列化属性的其他无效组合/设置会导致异常。

编辑:谢谢你,TonyB,我不知道设置临时文件的位置。对于那些将来遇到类似问题的人,您确实需要一个额外的配置标志:

<system.diagnostics>
  <switches>
    <add name="XmlSerialization.Compilation" value="1" />
  </switches>
</system.diagnostics>
<system.xml.serialization>
  <xmlSerializer tempFilesLocation="c:\\foo"/>
</system.xml.serialization>

即使在 Bar 属性上设置了一个 [XmlElement] 属性,在生成的序列化程序集中也没有提到它——这相当坚定地把它放在了一个默默吞下的错误(又名错误)的领域。或者设计者已经决定 [XmlIgnore] 对于无法设置的属性不再是必需的——您希望在发行说明、更改列表XmlIgnoreAttribute 文档中看到这一点。

4

2 回答 2

4

在 SP1 中, foo.Bar 属性是否得到正确反序列化?

在 SP1 之前,您将无法反序列化对象,因为 Bar 属性的 set 方法是私有的,因此 XmlSerializer 无法设置该值。我不确定 SP1 是如何做到的。

您可以尝试将其添加到您的 web.config/app.config

<system.xml.serialization> 
  <xmlSerializer tempFilesLocation="c:\\foo"/> 
</system.xml.serialization> 

这会将 XmlSerializer 生成的类放入 c:\foo 中,这样您就可以看到它在 SP1 与 RTM 中的作用

于 2008-08-29T20:20:59.180 回答
0

我更喜欢这种新的 (?) 行为,因为 XML 文档中没有提及 Bar,因此反序列化程序甚至不应该尝试设置它。

于 2008-08-29T21:41:26.503 回答