反序列化到List时XmlRootAttribute的位置

本文关键字:位置 XmlRootAttribute List 反序列化 | 更新日期: 2023-09-27 18:05:09

我有以下XML

<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Sites>
  <Site>
    <Code>TWTR</Code>
    <Name>twitter.com</Name>
  </Site>
  <Site>
    <Code>FB</Code>
    <Name>facebook.com</Name>
  </Site>
  <Site>
    <Code>SO</Code>
    <Name>stackoverflow.com</Name>
  </Site>
</Sites>

这是代码:

public class Program
{
    static void Main(string[] args)
    {
        var fs = new FileStream(@"D:'temp'Sites.xml", FileMode.Open);
        var serializer = new XmlSerializer(typeof(List<Site>));
        var instance = (List<Site>)serializer.Deserialize(fs);
    }
}
[XmlRoot("Sites")]
public class Site
{
    public string Code { get; set; }
    public string Name { get; set; }
}

得到的例外是:<Sites xmlns=''> was not expected.。出现此错误的原因通常是,我没有为XmlSerializer定义XmlRoot。但是正如你所看到的,我用XmlRootAttribute

来装饰Site

为了解决我的困惑,下面的技巧奏效了:

代替

var serializer = new XmlSerializer(typeof(List<Site>));

var serializer = new XmlSerializer(typeof(List<Site>), new XmlRootAttribute("Sites"));

我错过了什么吗?

反序列化到List时XmlRootAttribute的位置

如果您可以控制XML,那么只需更改:

<Sites> 

<ArrayOfSite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

如果您无法控制XML,请创建自己的集合并将其反序列化。

[XmlRoot("Sites")]
public class Sites : List<Site>
{
}

使用下列构造函数时要小心:

var serializer = new XmlSerializer(typeof(List<Site>), new XmlRootAttribute("Sites"));

正如微软在这里指出的,如果你不缓存与List<Site>相关的序列化器的实例,你将以内存泄漏告终…

动态生成程序集

为了提高性能,XML序列化基础设施动态生成要序列化和反序列化的程序集指定的类型。基础设施查找并重用这些程序集。此行为仅在使用以下构造函数时发生:

XmlSerializer.XmlSerializer(类型)

XmlSerializer。XmlSerializer(类型、字符串)

如果使用任何其他构造函数,则生成相同的程序集,但从未卸载,这导致内存泄漏和性能差。最简单的解决方法就是使用一个前面提到的两个构造函数。否则,你必须将程序集缓存到散列表中,如下所示例子。

没有使用添加到SiteXmlRoot属性,因为您没有反序列化类型为Site的对象。您正在反序列化类型为List<Site>的对象,这就是序列化程序查找XmlRoot属性的地方。

你的变通方法实际上是正确的解决方案。但是,如果您经常在程序中执行这种反序列化,请确保缓存XmlSerializer实例,因为该特定构造函数不会在内部缓存动态生成的程序集—这与您通常使用的构造函数相反。