What is serialize?
这个翻译非常无趣. 就好比有人给你一个英文单词"goooooooood",然后中文翻译就是"古德". 最后打破沙锅问到底,才知道"古德"的意思就是,很好好好好好好好好好好好(好连续发音)的意思. 照我看来,序列化也是一个模式的翻译. 这么写当然是为了替自己很多年都没弄清楚这个概念而把原因推到别人身上,哈哈.
英文辞典里serialize有两个解释:1,publish or broadcast(a story or play) in regular installments 2. arrange(something) in a series. 显然计算机术语是延伸了第一个意思,但是story变成了object, 对象而已. publish对象?
Why serialize?
Wikipedia:
In computer science, in the context of data storage and transmission, serialization is the process of converting an object into a sequence of bits so that it can be persisted on a storage medium (such as a file, or a memory buffer) or transmitted across a network connection link. When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object. For many complex objects, such as those that make extensive use of references, this process is not straightforward.
所以所谓序列化的目的: 持久化(persist)对象以便存储到某处(文件,缓存等等),或者用来在网络间传输.
How it works?
持久化就是把对象转化成有序的bits,然后接收方或者稍后从存储中读出来在反序列化(deserialize)得到原先的对象
序列化的好处是提供了:
方便的持久化对象, 也提供了一种实现远程调用的方法, 也是一种实现分布式对象的方法,尤其是在corba com这样的环境下, 也提供了一种探测随时间变化的对象状态的方法
.net里头,可以使用Serializeable attribute标识class为可序列化对象.如:
[Serializable]
class Employee
如果后续该class的版本增加新的方法,可以用OptionalField attribute来实现序列化的兼容性. 同时.net提供了SaopFormatter和XmlSerializer来支持可读性强的跨平台的XML序列化方法,也就是说,序列化的结果不是Binary,而是一个XML File.
Customize Serialize
有时候我们希望可以控制序列化的过程。例如上面提到的版本控制,或者对于其中某个属性进行一些加工处理。其实个人感觉这样的情形并不多见,不过还是有滴。这时候就需要自己来实现序列化的过程。
Traditional Method
传统方式就是实现ISerialzable接口,其中包含了一个函数GetObject。函数中的SerializationInfo类包含了一组Key/Value的数据结构,对应的就是你的变量名和值。因此通常的实现方式如下,注意用这种方式你可以自定义key名,另外如果你只是想存储对象而不需要反序列化的话,还可以添加别的自定义信息:
Code
[Serializable]
public class MyObject1: ISerializable
{
public int member1;
public string member2;
//TO-DO: Constructor for deserializing
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("M1", member1);
info.AddValue("M2", member2);
info.AddValue("M3", "This is new infomation.");
}
#endregion
}
这是第一步,为了实现反序列化,你需要自定义一个构造函数,参数跟GetObject一样,不同的是这回你是要取值并赋值给自己的对象了。
Code
[Serializable]
public class MyObject1: ISerializable
{
public int member1;
public string member2;
public MyObject1()
{ }
public MyObject1(SerializationInfo info, StreamingContext context)
{
member1 = info.GetInt32("M1");
member2 = info.GetString("M2");
}
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("M1", member1);
info.AddValue("M2", member2);
info.AddValue("M3", "This is new infomation.");
}
#endregion
}
Recommend Method
微软推荐的”The best practice and easiest way”,是采用类似Event的方式。但是实现同样用Attribute实现,非常简便。这几个attribute分别是:OnSerializedAttribute OnSerializingAttribute OnDeserializedAttribute OnDeserializingAttribute. 这个没什么好讲的,熟悉.NET的同学看字面意思就应该知道怎么起作用的。看微软的示例代码,注意78行被标注为[NonSerialized()]的成员也可以被重写:
Code
1
2
3using System;
4using System.IO;
5using System.Runtime.Serialization;
6using System.Runtime.Serialization.Formatters.Binary;
7
8public class Test
9{
10 public static void Main()
11 {
12 // Create a new TestSimpleObject object.
13 TestSimpleObject obj = new TestSimpleObject();
14
15 Console.WriteLine("\n Before serialization the object contains: ");
16 obj.Print();
17
18 // Open a file and serialize the object into binary format.
19 Stream stream = File.Open("DataFile.dat", FileMode.Create);
20 BinaryFormatter formatter = new BinaryFormatter();
21
22 try
23 {
24 formatter.Serialize(stream, obj);
25
26 // Print the object again to see the effect of the
27 //OnSerializedAttribute.
28 Console.WriteLine("\n After serialization the object contains: ");
29 obj.Print();
30
31 // Set the original variable to null.
32 obj = null;
33 stream.Close();
34
35 // Open the file "data.xml" and deserialize the object from it.
36 stream = File.Open("DataFile.dat", FileMode.Open);
37
38 // Deserialize the object from the data file.
39 obj = (TestSimpleObject)formatter.Deserialize(stream);
40
41 Console.WriteLine("\n After deserialization the object contains: ");
42 obj.Print();
43 }
44 catch (SerializationException se)
45 {
46 Console.WriteLine("Failed to serialize. Reason: " + se.Message);
47 throw;
48 }
49 catch (Exception exc)
50 {
51 Console.WriteLine("An exception occurred. Reason: " + exc.Message);
52 throw;
53 }
54 finally
55 {
56 stream.Close();
57 obj = null;
58 formatter = null;
59 }
60
61 }
62}
63
64
65// This is the object that will be serialized and deserialized.
66[Serializable()]
67public class TestSimpleObject
68{
69 // This member is serialized and deserialized with no change.
70 public int member1;
71
72 // The value of this field is set and reset during and
73 // after serialization.
74 private string member2;
75
76 // This field is not serialized. The OnDeserializedAttribute
77 // is used to set the member value after serialization.
78 [NonSerialized()]
79 public string member3;
80
81 // This field is set to null, but populated after deserialization.
82 private string member4;
83
84 // Constructor for the class.
85 public TestSimpleObject()
86 {
87 member1 = 11;
88 member2 = "Hello World!";
89 member3 = "This is a nonserialized value";
90 member4 = null;
91 }
92
93 public void Print()
94 {
95 Console.WriteLine("member1 = '{0}'", member1);
96 Console.WriteLine("member2 = '{0}'", member2);
97 Console.WriteLine("member3 = '{0}'", member3);
98 Console.WriteLine("member4 = '{0}'", member4);
99 }
100
101 [OnSerializing()]
102 internal void OnSerializingMethod(StreamingContext context)
103 {
104 member2 = "This value went into the data file during serialization.";
105 }
106
107 [OnSerialized()]
108 internal void OnSerializedMethod(StreamingContext context)
109 {
110 member2 = "This value was reset after serialization.";
111 }
112
113 [OnDeserializing()]
114 internal void OnDeserializingMethod(StreamingContext context)
115 {
116 member3 = "This value was set during deserialization";
117 }
118
119 [OnDeserialized()]
120 internal void OnDeserializedMethod(StreamingContext context)
121 {
122 member4 = "This value was set after deserialization.";
123 }
124}
125
126// Output:
127// Before serialization the object contains:
128// member1 = '11'
129// member2 = 'Hello World!'
130// member3 = 'This is a nonserialized value'
131// member4 = ''
132//
133// After serialization the object contains:
134// member1 = '11'
135// member2 = 'This value was reset after serialization.'
136// member3 = 'This is a nonserialized value'
137// member4 = ''
138//
139// After deserialization the object contains:
140// member1 = '11'
141// member2 = 'This value went into the data file during serialization.'
142// member3 = 'This value was set during deserialization'
143// member4 = 'This value was set after deserialization.'
144
145
Binary, Soap, XML Serialize
标准的序列化是Binary格式的,用BinaryFormatter实现。后来随着对可读性以及兼容性等等需求的出现,尤其是Web Service的兴起,SoapFormatter开始出现。但是这两个的工作原理都一模一样,无非是换了一个Formatter而已。前者性能高,后者兼容性好,可读性强。
这两者在Remoting中起着重要的作用。然而其实平时就算不做Remoting也可以用到相应的概念。尤其是XML出现以后,很多mini程序开始采用XML格式替代数据库来进行数据存储。当然,你可以用XPath之类的东西一个一个的读呀写呀,不过或许,你也想过,能不能就像序列化一样处理对象呢?比如,blog程序中用户发了一篇帖子,我的Post对象就直接序列化成文件呢?答案是有。
Remoting & Serialize