1. 概述
应用程序间传递数据,需要先将数据对象转化为字符流或字节流的形式,然后接收端收到后再转化回原始的数据对象。这就是序列化与反序列化。
本章介绍 .net中的序列化与反序列化、序列化器的种类 以及 为序列化配置对象。
2. 主要内容
2.1 序列化与反序列化
序列化只能保存对象的数据部分,不能保存方法部分。可以创建custom data transfer object(DTO)来只保存指定的数据信息。
.net平台提供三种类型的序列化:
① XmlSerializer:
[Serializable]
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
XmlSerializer serializer = new XmlSerializer(typeof(Person));
string xml;
using (StringWriter stringWriter = new StringWriter())
{
Person p = new Person
{
FirstName = “John”,
LastName = “Doe”,
Age = 42
};
serializer.Serialize(stringWriter, p);
xml = stringWriter.ToString();
}
Console.WriteLine(xml);
using (StringReader stringReader = new StringReader(xml))
{
Person p = (Person)serializer.Deserialize(stringReader);
Console.WriteLine(“{0} {1} is {2} years old”, p.FirstName, p.LastName, p.Age);
}
常用的几个attribute:
XmlIgnore
XmlAttribute
XmlElement
XmlArray
XmlArrayItem
[Serializable]
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
[Serializable]
public class Order
{
[XmlAttribute]
public int ID { get; set; }
[XmlIgnore]
public bool IsDirty { get; set; }
[XmlArray(“Lines”)]
[XmlArrayItem(“OrderLine”)]
public List<OrderLine> OrderLines { get; set; }
}
[Serializable]
public class VIPOrder : Order
{
public string Description { get; set; }
}
[Serializable]
public class OrderLine
{
[XmlAttribute]
public int ID { get; set; }
[XmlAttribute]
public int Amount { get; set; }
[XmlElement(“OrderedProduct”)]
public Product Product { get; set; }
}
[Serializable]
public class Product
{
[XmlAttribute]
public int ID { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
}
private static Order CreateOrder()
{
Product p1 = new Product { ID = 1, Description = “p2”, Price = 9 };
Product p2 = new Product { ID = 2, Description = “p3”, Price = 6 };
Order order = new VIPOrder
{
ID = 4,
Description = “Order for John Doe. Use the nice giftwrap”,
OrderLines = new List<OrderLine>
{
new OrderLine { ID = 5, Amount = 1, Product = p1},
new OrderLine { ID = 6 ,Amount = 10, Product = p2},
}
};
return order;
}
XmlSerializer serializer = new XmlSerializer(typeof(Order),
new Type[] { typeof(VIPOrder) });
string xml;
using (StringWriter stringWriter = new StringWriter())
{
Order order = CreateOrder();
serializer.Serialize(stringWriter, order);
xml = stringWriter.ToString();
}
using (StringReader stringReader = new StringReader(xml))
{
Order o = (Order)serializer.Deserialize(stringReader);
// Use the order
}
② binary serialization
[Serializable]
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
private bool isDirty = false;
}
Person p = new Person
{
Id = 1,
Name = “John Doe”
};
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new FileStream(“data.bin”, FileMode.Create))
{
formatter.Serialize(stream, p);
}
using (Stream stream = new FileStream(“data.bin”, FileMode.Open))
{
Person dp = (Person)formatter.Deserialize(stream);
}
可以使用下列attributes来控制序列化与反序列化的过程
OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
OnSerializingAttribute
[Serializable]
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
[NonSerialized]
private bool isDirty = false;
[OnSerializing()]
internal void OnSerializingMethod(StreamingContext context)
{
Console.WriteLine(“OnSerializing.”);
}
[OnSerialized()]
internal void OnSerializedMethod(StreamingContext context)
{
Console.WriteLine(“OnSerialized.”);
}
[OnDeserializing()]
internal void OnDeserializingMethod(StreamingContext context)
{
Console.WriteLine(“OnDeserializing.”);
}
[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context)
{
Console.WriteLine(“OnSerialized.”);
}
}
通过实现ISerializable接口,可以进行更精细的序列化控制。
[Serializable]
public class PersonComplex : ISerializable
{
public int Id { get; set; }
public string Name { get; set; }
private bool isDirty = false;
public PersonComplex() { }
protected PersonComplex(SerializationInfo info, StreamingContext context)
{
Id = info.GetInt32(“Value1”);
Name = info.GetString(“Value2”);
isDirty = info.GetBoolean(“Value3”);
}
[System.Security.Permissions.SecurityPermission(SecurityAction.Demand,
SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(“Value1”, Id);
info.AddValue(“Value2”, Name);
info.AddValue(“Value3”, isDirty);
}
}
③ 使用DataContract
WCF中使用DataContract来将对象序列化为Xml或者Json格式。
[DataContract]
public class PersonDataContract
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
private bool isDirty = false;
}
④ 使用Json序列化器
[DataContract]
public class Person
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
Person p = new Person
{
Id = 1,
Name = “John Doe”
};
using (MemoryStream stream = new MemoryStream())
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
ser.WriteObject(stream, p);
stream.Position = 0;
StreamReader streamReader = new StreamReader(stream);
Console.WriteLine(streamReader.ReadToEnd()); // Displays {“Id”:1,”Name”:”John Doe”}
stream.Position = 0;
Person result = (Person)ser.ReadObject(stream);
}
3. 总结
① 序列化 是将一个对象转化为一个字符流或者字节流的过程。反序列化正好相反。
② 可以使用XmlSerializer来实现Xml格式的序列化。还可以使用指定的attributes来配置序列化操作。
③ 可以使用BinaryFormatter来实现二进制格式的序列化。
④ Wcf中使用DataContractSerializer来配置序列化操作。
⑤ 使用DataContractJsonSerializer来创建轻型文本格式Json。