和BinaryFormatter序列化一样,做一个可以序列化的类Person:
namespace Serializable
{
[Serializable] //不可少!
public class Person
{
private String name;
private String sex;
private int age;
public Person() //XmlSerializer序列化要求一定要有无参数构造函数
{
name = "";
sex = "";
age = 0;
}
public Person(String n, String s, int a)
{
name = n;
sex = s;
age = a;
}
public String Name
{
get
{
return name;
}
set
{
name = value;
}
}
public String Sex
{
get
{
return sex;
}
set
{
sex = value;
}
}
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
}
}
//主运行程序
namespace Serializable
{
class Program
{
static void Main(string[] args)
{
Person p1 = new Person("张三", "男", 20);
//序列化
try
{
FileStream fs = new FileStream("serialiable.xml", FileMode.Create);
XmlSerializer xs = new XmlSerializer(typeof(Person));
xs.Serialize(fs, p1);
fs.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("序列化成功!");
Console.Read();
//反序列化
try
{
FileStream fs = new FileStream("serialiable.xml", FileMode.Open, FileAccess.Read);
XmlSerializer xs = new XmlSerializer(typeof(Person));
Person p = (Person)xs.Deserialize(fs);
Console.WriteLine(p.Name + p.Sex + p.Age);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.Read();
Console.Read();
}
}
}
结果图:
生成的XML文件:
这篇随笔对应的.Net命名空间是System.Xml.Serialization;文中的示例代码需要引用这个命名空间。
.Net程序执行时,对象都驻留在内存中;内存中的对象如果需要传递给其他系统使用;或者在关机时需要保存下来以便下次再次启动程序使用就需要序列化和反序列化。
范围:本文只介绍xml序列化,其实序列化可以是二进制的序列化,也可以是其他格式的序列化。
static void Main(string[] args)
XmlSerializer serializer = new XmlSerializer(typeof(int));
serializer.Serialize(Console.Out, i);
上面代码对int i进行了序列化,并将序列化的结果输出到了控制台,输出结果如下
"1.0" encoding="gb2312"?>
可以将上述序列化的xml进行反序列化,如下代码
static void Main(string[] args)
using (StringReader rdr = new StringReader(@"
XmlSerializer serializer = new XmlSerializer(typeof(int));
int i = (int)serializer.Deserialize(rdr);
Console.WriteLine("i = " + i);
以上代码用最简单的方式说明了xml序列化和反序列化的过程,.Net系统类库为我们做了大量的工作,序列化和反序列化都非常简单。但是在现实中业务需求往往比较复杂,不可能只简单的序列化一个int变量,显示中我们需要对复杂类型进行可控制的序列化。
System.Xml.Serialization命名空间中有一系列的特性类,用来控制复杂类型序列化的控制。例如XmlElementAttribute、XmlAttributeAttribute、XmlArrayAttribute、XmlArrayItemAttribute、XmlRootAttribute等等。
看一个小例子,有一个自定义类Cat,Cat类有三个属性分别为Color,Saying,Speed。
namespace UseXmlSerialization
static void Main(string[] args)
var c = new Cat { Color = "White", Speed = 10, Saying = "White or black, so long as the cat can catch mice, it is a good cat" };
XmlSerializer serializer = new XmlSerializer(typeof(Cat));
serializer.Serialize(Console.Out, c);
public string Color { get; set; }
public int Speed { get; set; }
public string Saying { get; set; }
可以使用XmlElement指定属性序列化为子节点(默认情况会序列化为子节点);或者使用XmlAttribute特性制定属性序列化为Xml节点的属性;还可以通过XmlIgnore特性修饰要求序列化程序不序列化修饰属性。
数组的Xml序列化需要使用XmlArrayAttribute和XmlArrayItemAttribute;XmlArrayAttribute指定数组元素的Xml节点名,XmlArrayItemAttribute指定数组元素的Xml节点名。
using System.Collections.Generic;
using System.Xml.Serialization;
namespace UseXmlSerialization
static void Main(string[] args)
var cWhite = new Cat { Color = "White", Speed = 10, Saying = "White or black, so long as the cat can catch mice, it is a good cat" };
var cBlack = new Cat { Color = "Black", Speed = 10, Saying = "White or black, so long as the cat can catch mice, it is a good cat" };
CatCollection cc = new CatCollection { Cats = new Cat[] { cWhite,cBlack} };
XmlSerializer serializer = new XmlSerializer(typeof(CatCollection));
serializer.Serialize(Console.Out, cc);
public class CatCollection
[XmlArray("items"),XmlArrayItem("item")]
public Cat[] Cats { get; set; }
public string Color { get; set; }
public int Speed { get; set; }
public string Saying { get; set; }
"1.0" encoding="gb2312"?>
"http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://ww
w.w3.org/2001/XMLSchema">
White or black, so long as the cat can catch mice, it is a good
White or black, so long as the cat can catch mice, it is a good
XmlSerializer内存泄漏问题:
仔细看了下msdn,确实存在泄漏的情况,msdn说明如下:
为了提高性能,XML 序列化基础结构将动态生成程序集,以序列化和反序列化指定类型。此基础结构将查找并重复使用这些程序集。此行为仅在使用以下构造函数时发生:
XmlSerializer.XmlSerializer(Type, String)
如果使用任何其他构造函数,则会生成同一程序集的多个版本,且绝不会被卸载,这将导致内存泄漏和性能降低。最简单的解决方案是使用先前提到的两个构造函数的其中一个。否则,必须在 Hashtable 中缓存程序集,如以下示例中所示。
也就是说我们在使用XmlSerializer序列化,初始化XmlSerializer对象时最好使用下面两个构造函数否则会引起内存泄漏。
XmlSerializer.XmlSerializer(Type, String)