反序列化到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"));
我错过了什么吗?
如果您可以控制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(类型、字符串)
如果使用任何其他构造函数,则生成相同的程序集,但从未卸载,这导致内存泄漏和性能差。最简单的解决方法就是使用一个前面提到的两个构造函数。否则,你必须将程序集缓存到散列表中,如下所示例子。
没有使用添加到Site
的XmlRoot
属性,因为您没有反序列化类型为Site
的对象。您正在反序列化类型为List<Site>
的对象,这就是序列化程序查找XmlRoot
属性的地方。
你的变通方法实际上是正确的解决方案。但是,如果您经常在程序中执行这种反序列化,请确保缓存XmlSerializer
实例,因为该特定构造函数不会在内部缓存动态生成的程序集—这与您通常使用的构造函数相反。