使用.Net使用XmlSerializer有哪些限制(如果有的话)?例如,您可以将图像序列化为XML吗?
我通常发现XmlSerializer对于任何不仅仅是DTO的POCO来说都是一个糟糕的选择.如果您需要特定的XML,您可以使用Xml*属性和/或IXmlSerializable路由 - 但是您会留下一个非常糟糕的对象.
出于某些目的,它仍然是一个明显的选择 - 即使有它的局限性.但是,为了简单地存储和重新加载数据,我发现BinaryFormatter是一个更容易的选择,具有更少的陷阱.
这里列出了一些与XmlSerializer有关的烦恼 - 大部分时间我都被咬过,其他一些我在MSDN找到了:
需要public,没有args构造函数
仅序列化公共读/写属性和字段
需要知道所有类型
实际上调用get_*和set_*,因此将运行验证等.这可能是好的也可能是坏的(考虑一下电话的顺序)
将仅序列化符合特定规则的IEnumerable或ICollection集合
XmlSerializer为实现IEnumerable或ICollection的类提供特殊处理.实现IEnumerable的类必须实现一个带有单个参数的公共Add方法.Add方法的参数必须与从GetEnumerator返回的值的Current属性返回的类型相同,或者该类型的base之一.
除了IEnumerable之外,实现ICollection(例如CollectionBase)的类必须具有一个公共Item索引属性(C#中的索引器),该属性采用整数,并且它必须具有integer类型的公共Count属性.Add方法的参数必须与Item属性返回的类型相同,或者是该类型的基础之一.对于实现ICollection的类,要从序列化的Item属性中检索要序列化的值,而不是通过调用GetEnumerator.
不序列化IDictionary
使用动态生成的程序集,这些程序集可能无法从应用程序域中卸载.
为了提高性能,XML序列化基础结构动态生成程序集以序列化和反序列化指定的类型.基础结构查找并重用这些程序集.仅当使用以下构造函数时,才会出现此问题:
XmlSerializer.XmlSerializer(Type)XmlSerializer.XmlSerializer(Type,String)
如果使用任何其他构造函数,则会生成同一程序集的多个版本,并且永远不会卸载,这会导致内存泄漏和性能下降.
无法序列化ArrayList []或List
还有其他奇怪的边缘情况
如果满足下列条件,则无法实例化XmlSerializer以序列化枚举:枚举的类型为unsigned long(C#中为ulong),枚举包含值大于9,223,372,036,854,775,807的任何成员.
XmlSerializer类不再序列化标记为[已废弃]的对象.
您必须有权写入临时目录(由TEMP环境变量定义)以反序列化对象.
需要读取.InnerException以获取有关错误的任何有用信息
XmlSerializer有一些缺点.
它必须知道所有被序列化的类型.您不能通过表示序列化程序不知道的类型的接口传递它.
它不能做循环引用.
如果在对象图中多次引用,它将多次序列化同一个对象.
无法处理私有字段序列化.
我(愚蠢地)写了我自己的序列化器来解决其中的一些问题.不要那样做; 这是一项很多工作,你会在几个月后发现微妙的错误.我在编写自己的序列化器和格式化程序时获得的唯一一点就是对对象图序列化中涉及的细节的更大理解.
当WCF问世时,我找到了NetDataContractSerializer.它完成了XmlSerializer不能完成的所有内容.它以与XmlSerializer类似的方式驱动序列化.一个用属性修饰各种属性或字段,以通知序列化程序要序列化的内容.我替换了我用NetDataContractSerializer编写的自定义序列化程序,并对结果非常满意.我会极力推荐它.