XmlSerializer在命名空间using System.Xml.Serialization下。
序列化和反序列化的代码:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
public class PublicFunction
{
//序列化到XmlNode
public static void Serialize<T>(T t, out XmlNode node)
{
XmlDocument doc = new XmlDocument();
using (MemoryStream ms = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(T), typeof(T).Assembly.GetName().Name);
serializer.Serialize(ms, t);
ms.Position = 0;
doc.Load(ms);
node = doc.LastChild;
}
}
//反序列化XmlNode中的数据
public static void DeSerialize<T>(XmlNode node, out T t)
{
XmlSerializer serializer = new XmlSerializer(typeof(T), typeof(T).Assembly.GetName().Name);
XmlNodeReader reader = new XmlNodeReader(node);
t=(T)serializer.Deserialize(reader);
} //序列化到文件
public static void SerializeFile<T>(T t, string filepath)
{
using(XmlWriter writer = new XmlTextWriter(filepath, Encoding.UTF8))
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(writer,t);
}
} //将文件中的内容反序列化
public static void DeSerializeFile<T>(string Filepath,out T t)
{
t = default(T);
using (XmlReader reader = new XmlTextReader(Filepath))
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Deserialize(reader);
}
}
}
}
XmlSerializer序列化规则:
1.只能序列化public成员变量,protected、private、public static 声明的字段都不支持序列化。
2.对象属性必须是可读可写。
3.对象必须要有一个无参构造函数,用于反序列化。
4.序列化的顺序和字段定义的顺序保持一致。
5.序列化子类,而声明的是基类时,需要在基类中使用XmlInclude声明子类类型,例如下面的listCCAbstract字段。
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Aa a = new Aa();
PublicFunction.SerializeFile<Aa>(a, @"D:\1.txt");
}
}
[XmlRoot("AaRoot")]
public class Aa
{
public static string StaticParam;
[XmlAttribute("Name")]
public string name; [XmlIgnore]
public string Ignore;
protected string proparam;
private int age;
public int pAttribute
{
get;
set;
}
[XmlArray("List")]
[XmlArrayItem("Item")]
public List<CCAbstract> listCCAbstract { get; set; } public Aa()
{
StaticParam = "StaticParam";
this.name = "Aa";
this.proparam = "Praparam";
this.age = 23;
pAttribute = 23;
Ignore = "Ignpore";
listCCAbstract = new List<CCAbstract> { new Cc("testCcAbstract") };
}
} [XmlInclude(typeof(Cc))]
public abstract class CCAbstract
{
} public class Cc:CCAbstract
{
public string CName;
public Cc()
{
}
public Cc(string name)
{
this.CName=name;
}
}
}
序列化后的xml内容为:
<?xml version="1.0" encoding="utf-8"?>
<AaRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Name="Aa">
<pAttribute>23</pAttribute>
<List>
<Item xsi:type="Cc">
<CName>testCcAbstract</CName>
</Item>
</List>
</AaRoot>
可以看到XmlRoot可以指定根结点名称,name不再作为XmlElement而是变成了AaRoot的属性。XmlIgnore标签标识的字段不进行序列化,protected、private、public static 声明的字段都不支持序列化。XmlArray可以指定List类型序列化后的名称,XmlArrayItem则对应List中的元素。
6.尽量使用XmlSerializer(Type)、XmlSerializer(Type,String)这两种构造函数,如果使用其它构造函数则会导致内存泄漏。
详情请看
https://msdn.microsoft.com/zh-cn/library/system.xml.serialization.xmlserializer(VS.80).aspx
为了提高性能,XML 序列化基础结构动态生成程序集,以便对指定类型进行序列化和反序列化。该基础结构将找到并重新使用这些程序集。仅当使用以下构造函数时,才会发生此行为:
System.Xml.Serialization.XmlSerializer(Type)
System.Xml.Serialization.XmlSerializer(Type,String)
如果使用任何其他构造函数,则将生成同一个程序集的多个版本,这些版本始终不予卸载,从而导致内存泄漏和性能低下。最简单的解决方案是使用上面两个构造函数中的一个。