我看过很多关于 .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 属性即可。

我的谷歌显然无法找到此类更改的文档。是否有一个更改列表列出了此更改(以及可能会跳起来并大喊“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 文档.

有帮助吗?

解决方案

在 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 中做了什么

其他提示

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top