3 、使用 XmlSerializer 进行串行化
串行化的文件是xml格式,能串行泛型,继承等关系对象,但是不能串行只包含私有成员的对象,有一定的限制,比BinaryFormatter弱一点,比Soap强一点。其中它串行化继承关系对象时,需要使用xmlarrayitem特性进行特殊标记。
对象中包含的所有类都必须有默认构造函数,否则反射失败。
[Serializable()] public class XmlSerialize { private int id; public int ID { get { return id; } set { id = value; } } private string name; public string Name { get { return name; } set { name = value; } } private SexType sex; public SexType Sex { get { return sex; } set { sex = value; } } private List< string > listStr; public List< string > ListStr { get { return listStr; } set { listStr = value; } } private List<Item> listItem; [XmlArrayItem(typeof (Item)), XmlArrayItem( typeof (ItemSub))] public List<Item> ListItem { get { return listItem; } set { listItem = value; } } private Item[] arrayItem; [XmlArrayItem(ElementName = "Item" , IsNullable = true , Type = typeof (Item), Namespace = "http://www.cpandl.com" ), XmlArrayItem(ElementName = "BookItem" , IsNullable = true , Type = typeof (ItemSub), Namespace = "http://www.cohowinery.com" )] [XmlArray] public Item[] ArrayItem { get { return arrayItem; } set { arrayItem = value; } } private ListBuffer buffer = new ListBuffer(); public ListBuffer Buffer { get { return buffer; } set { buffer = value; } } private ListBufferSub bufferSub = new ListBufferSub(); public ListBufferSub BufferSub { get { return bufferSub; } set { bufferSub = value; } } } public sealed class ConfigurationManagerXmlSerialize { private static string path = System.Windows.Forms.Application.StartupPath + "\\XmlSerialize.xml" ; public static XmlSerialize Get() { if (!File.Exists(path)) return null ; XmlSerializer b = new XmlSerializer( typeof (XmlSerialize)); using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { return (XmlSerialize)b.Deserialize(fs); } } public static void Set(XmlSerialize hr) { XmlSerializer b = new XmlSerializer( typeof (XmlSerialize)); using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write)) { b.Serialize(fs, hr); } } }
备注:
xml序列化也能序列化很多类,但是对于太过复杂的类,还是无能为力。
xml反序列化需要类以及类中包含的所有对象都有默认构造函数,否则序列化异常。
xml序列化在处理包含集合成员时,如果集合中元素包含继承关系,那么需要在集合成员上使用特性XmlArrayItem,用了标记此集合中包含哪几种具体类型。
xml序列化有如下限制:
(1)需序列化的字段必须是公共的(public)
(2)需要序列化的类都必须有一个无参的构造函数
(3)枚举变量可序列化为字符串,无需用[XmlInclude]
(4)导出非基本类型对象,都必须用[XmlInclude]事先声明。该规则递归作用到子元素
如导出ArrayList对象,若其成员是自定义的,需预包含处理:
using System.Xml.Serialization;
[XmlInclude(typeof(自定义类))]
(5)Attribute中的IsNullable参数若等于false,表示若元素为null则不显示该元素。
也就是说:针对值类型(如结构体)该功能是实效的
若数组包含了100个空间,填充了10个类对象,则序列化后只显示10个节点
若数组包含了100个空间,填充了10个结构体对象,则序列化后会显示100个节点
(6)真正无法XML序列化的情况
某些类就是无法XML序列化的(即使使用了[XmlInclude])
IDictionary(如HashTable)
System.Drawing.Color
System.Drawing.Font
SecurityAttribute声明
父类对象赋予子类对象值的情况
对象间循环引用
(7)对于无法XML序列化的对象,可考虑
使用自定义xml序列化(实现IXmlSerializable接口)
实现IDictionary的类,可考虑(1)用其它集合类替代;(2)用类封装之,并提供Add和this函数
某些类型需要先经过转换,然后才能序列化为 XML。如XML序列化System.Drawing.Color,可先用ToArgb()将其转换为整数
过于复杂的对象用xml序列化不便的话,可考虑用二进制序列化
在很多情况下,二进制序列化对对象的序列化信息更加完整、准确。