C# Xml序列化与反序列化
Xml文本的序列化与反序列化:
public static class XmlSerializeHelper { // 序列化:对象 -> Xml文本 public static string SerializeToXmlString(object obj) { StringBuilder buffer = new StringBuilder(); using (TextWriter writer = new StringWriter(buffer)) { XmlSerializer xmlSrlzer = new XmlSerializer(obj.GetType()); xmlSrlzer.Serialize(writer, obj); } return buffer.ToString(); } // 反序列化:Xml文本 -> 对象 public static TClass DeserializeFromXmlString<TClass>(string xml) { TClass obj; using (StringReader reader = new StringReader(xml)) { XmlSerializer xmlSrlzer = new XmlSerializer(typeof(TClass)); obj = (TClass)xmlSrlzer.Deserialize(reader); } return obj; } // 序列化:对象 -> Xml文件 public static void SerializeToXmlFile(object obj, string file) { using(TextWriter writer = new StreamWriter(file)) { XmlSerializer serializer = new XmlSerializer(obj.GetType()); serializer.Serialize(writer, obj); } } // 反序列化:Xml文本 -> 对象 public static TClass DeserializeFromXmlFile<TClass>(string file) { TClass obj; using (FileStream reader = new FileStream(file, FileMode.Open)) { XmlSerializer xmlSrlzer = new XmlSerializer(typeof(TClass)); obj = (TClass)xmlSrlzer.Deserialize(reader); } return obj; } }
空对象序列化后的文本:
<?xml version="1.0" encoding="utf-16"?> <MyClassName xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
根节点名:
根节点名“MyClassName”就是类名,反序列化时,根节点名必须与类名一致。
可以通过XmlRootAttribute自定义根节点名,反序列化时,根节点名必须与自定义的跟节点名一致。
无参构造函数:
序列化时,不会调用无参构造函数,但如果没有无参构造函数,序列化报异常。
反序列化时,会首先调用无参构造函数构造对象,然后反序列化属性值。
无参构造函数设成private无影响。
字段与属性:
public的字段与属性都会被序列化,private的字段和属性不会被序列化。
基本类型:<Field>value</Field> Field:字段或属性名,Value是ToString()的返回值。
List<string>:<StringList><string>s1</string><string>s2</string></StringList> StringList:字段或属性名
List<int>:<IntList><int>1</int><int>2</int></IntList> IntList:字段或属性名
嵌套对象:<SubObj><addr>1</addr><value>2</value></SubObj>
对象List:
<SubObjList> <SubClass> <addr>1</addr> <value>1</value> </SubClass> <SubClass> <addr>2</addr> <value>2</value> </SubClass> </SubObjList>
泛型对象List:
<GenericList> <GenericClassOfInt32String> <!-- GenericClass<T1, T2> --> <val1>1</val1> <val2>b</val2> </GenericClassOfInt32String> <GenericClassOfInt32String> <val1>2</val1> <val2>d</val2> </GenericClassOfInt32String> </GenericList>
Array和List的序列化文本是一样的。
反序列化时,XML中没有的字段保留初始化值,XML中多出的字段直接忽略,不会报异常。
类继承:
类型与对象相同:对XML序列化无影响,能访问的属性或字段就能序列化与反序列化。
使用基类属性保存派生类对象,需要在基类上添加[XmlInclude(typeof(ExtendClass))],序列化后的XML文本中会多出 xsi:type="ExtendClass"。
接口不能序列化。
[XmlInclude(typeof(ExtendClass1))] [XmlInclude(typeof(ExtendClass2))] public class BaseClass { public int BP { get; set; } } public class ExtendClass1 : BaseClass { public int EP1 { get; set; } } public class ExtendClass2 : BaseClass { public int EP2 { get; set; } } public class MyClassName { public List<BaseClass> ObjList{ get; set; } }
<?xml version="1.0" encoding="utf-8"?> <MyClassName xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <ObjList> <BaseClass xsi:type="ExtendClass1"> <BP>1</BP> <EP1>11</EP1> </BaseClass> <BaseClass xsi:type="ExtendClass2"> <BP>2</BP> <EP2>22</EP2> </BaseClass> </ObjList> </MyClassName>
Dictionary:
不能序列化,可以使用SerializableDictionary(网上有现成的)。
[DefaultValue(true)]:
属性上加了该Attribute之后,如果值与DefaultValue相同,XML中不会生成节点,反序列化时却不会设置成DefaultValue,需要在构造函数里通过反射来设置DefaultValue。
去除xmlns:xsd:
StringBuilder buffer = new StringBuilder(); using (TextWriter writer = new StringWriter(buffer)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlSerializer xmlSrlzer = new XmlSerializer(obj.GetType()); xmlSrlzer.Serialize(writer, obj, ns); }
[XmlAttribute]实现XML属性:
public class SubClass { [XmlAttribute] public int ID { get; set; } public string Name { get; set; } } public class MyClassName { [XmlAttribute] public int Type { get; set; } public int Num { get; set; } public SubClass Sub { get; set; } }
<?xml version="1.0" encoding="utf-16"?> <MyClassName Type="0"> <Num>100</Num> <Sub ID="1"> <Name>HAHA</Name> </Sub> </MyClassName>