.NET 3.5 SP1中的XmlSerializer更改

时间:2020-03-05 18:45:08  来源:igfitidea点击:

我已经看到了许多有关.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:

Unable to generate a temporary class (result=1).
  error CS0200: Property or indexer 'ConsoleApplication2.Foo.Bar' cannot be assign to -- it is read only

当然,使其在RTM下运行所需要做的就是向Bar属性添加[XmlIgnore]。

我的Google Fu显然不适合查找此类更改的文档。是否有任何更改列表列出了此更改(以及可能会跳起来并大喊"陷阱"的类似的内部更改)?这是错误还是功能?

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

这使我更倾向于将其视为错误,尤其是如果我为Foo.Bar设置了[XmlElement]属性。如果它无法执行我要求的操作,则应该抛出异常,而不是无视Foo.Bar。 XML序列化属性的其他无效组合/设置会导致异常。

编辑:谢谢,TonyB,我不知道有关设置临时文件的位置。对于将来遇到类似问题的用户,我们确实需要一个额外的config标志:

<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 vs RTM中的作用。

回答

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