.NET 3.5 SP1中的XmlSerializer更改
我已经看到了许多有关.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的信息,因此反序列化器甚至不应尝试对其进行设置。