反序列化为List时的XmlRootAttribute放置

时间:2013-03-21 10:08:39

标签: c# xml xml-serialization

我有以下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时,通常会出现此错误的原因。但正如您所看到的,我通过使用Site

装饰班级XmlRootAttribute来做到这一点

为了完成我的困惑,以下技巧有效:

替换

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

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

我错过了什么吗?

2 个答案:

答案 0 :(得分:5)

如果您可以控制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"));

正如微软指出here,如果你没有缓存与List<Site>相关联的序列化程序的实例,你最终会泄漏内存......

  

动态生成的程序集

     

提高性能,XML序列化基础架构   动态生成程序集以序列化和反序列化   指定的类型。基础结构查找并重用这些程序集。   仅当使用以下构造函数时才会出现此问题:

     

XmlSerializer.XmlSerializer(类型):

     

XmlSerializer.XmlSerializer(Type,String)

     

如果您使用任何其他构造函数,则使用多个版本   生成相同的装配并且从不卸载,这导致a   内存泄漏和性能不佳。最简单的解决方案是使用一个   前面提到的两个构造函数。否则,你必须   将程序集缓存在Hashtable中,如下所示   示例

答案 1 :(得分:3)

您未添加XmlRoot添加到Site的{​​{1}}属性,因为您没有反序列化Site类型的对象。您正在反序列化List<Site>类型的对象,这是序列化程序查找XmlRoot属性的位置。

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