我最近学习remoting和web服务时,总是看到一个重要的字眼"序列化".
那什么是序列化呢?
以前我也模模糊糊.
为了搞清楚,请和我一起来序列化学习之旅吧.
让我们先看看序列化的定义,以下是微软的说明:
序列化可被定义为将对象的状态存储到存储媒介中的过程。在此过程中,对象的公共字段和私有字段以及类的名称(包括包含该类的程序集)都被转换为字节流,然后写入数据流。在以后反序列化该对象时,创建原始对象的精确复本
序列化一般用在2种地方:
1.将数据保持到存储中
例如:我知道在Asp.Net Forums中有.Net中序列化和反序列化的应用
在Forums中,有些内容是不固定的,如用户资料,除了一些基本资料,可能还要MSN、个人主页、签名等.我们一般是一个属性对应于表中的一个字段,要是以后我们增加一些新属性,就得增加表字段,还要修改存储过程,这样其不麻烦?
在Asp.Net Forums中把用户资料序列化为2进制,这样用一个表字段就可以解决问题,并且扩展性好。
2.通过值将对象从一个应用程序域发送到另一个应用程序域中
remoting和web服务就是典型的应用
说多了没用,让我们来一段代码吧
先定义一个类
1
using
System;
2
3
namespace
SerializTest
4
{
5
[Serializable]
6
public
class
Class2
7
{
8
private
string
name;
9
[NonSerialized]
10
private
int
account;
11
12
public
Class2(
string
name,
int
account)
13
{
14
this
.account
=
account;
15
this
.name
=
name;
16
}
17
18
public
int
Account
19
{
20
get
21
{
22
return
account;
23
}
24
}
25
26
public
string
Name
27
{
28
get
29
{
30
return
name;
31
}
32
}
33
}
34
}
35

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

序列化一个类的最简单的方式是使用Serializable属性
当然还可以通过在对象上实现ISerializable接口,自定义序列化
标记了Serializable属性的类,类里面的所有成员都将被序列化,私有的变量也在内
当然我们也可以有选择的序列化类里面的字段
例如类里面的一些敏感数据,我们可以不对其进行序列化
通过用NonSerialized属性标记成员变量,可以防止它们被序列化
NonSerialized属性只可以用在类的某个字段上
好了,再来一段俺喜欢的控制台来看看到底是怎么回事
1
using
System;
2
using
System.IO;
3
using
System.Runtime.Serialization;
4
using
System.Runtime.Serialization.Formatters.Binary;
5
using
System.Runtime.Serialization.Formatters.Soap;
6
7
namespace
SerializTest
8
{
9
class
Class1
10
{
11
[STAThread]
12
static
void
Main(
string
[] args)
13
{
14
string
fileName
=
"
MyFile.dat
"
;
15
Class2 my
=
new
Class2(
"
Serializ TestSerializ
"
,
987
);
16
Console.WriteLine(
"
初始化Class2类的一个实例my,my的账号=987,my的名字=Serializ TestSerializ
"
);
17
18
//
序列化过程开始,我们把Class2的实例二进制序列化到文件MyFile.dat中
19
IFormatter formatter1
=
new
BinaryFormatter();
20
Stream stream1
=
new
FileStream(fileName, FileMode.Create, FileAccess.Write,FileShare.None);
21
formatter1.Serialize(stream1,my);
22
stream1 .Close();
23
24
//
反序列化过程开始,我们把Class2的实例从文件MyFile.dat中取出来
25
IFormatter formatter
=
new
BinaryFormatter();
26
Stream stream
=
new
FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
27
Class2 c2
=
(Class2) formatter.Deserialize(stream);
28
stream.Close();
29
30
Console.WriteLine(
"
c2的名字=
"
+
c2.Name );
31
Console.WriteLine(
"
c2的账号=
"
+
c2.Account.ToString() );
32
33
Console.ReadLine();
34
}
35
}
36
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36


我们可以看到由于类Class2的account字段运用了NonSerialized属性
反序列化后我们是看不到Class2类实例的账号,只能看到名字
让我们再看一段,同时序列化多个对象的代码
1
using
System;
2
using
System.IO;
3
using
System.Runtime.Serialization;
4
using
System.Runtime.Serialization.Formatters.Binary;
5
using
System.Runtime.Serialization.Formatters.Soap;
6
7
namespace
SerializTest
8
{
9
class
Class1
10
{
11
[STAThread]
12
static
void
Main(
string
[] args)
13
{
14
string
fileName
=
"
MyFile.dat
"
;
15
Class2[] myClass
=
{
new
Class2(
"
a
"
,
123
),
new
Class2(
"
b
"
,
456
),
new
Class2(
"
c
"
,
789
)}
;
16
17
//
序列化过程开始
18
//
我们把类的几个实例序列化到一个文件中,这样比起分别序列化可以节约空间
19
IFormatter formatter
=
new
BinaryFormatter();
20
Stream stream
=
new
FileStream(fileName, FileMode.Create, FileAccess.Write,FileShare.None);
21
for
(
int
i
=
0
;i
<
myClass.Length;i
++
)
22
{
23
formatter.Serialize(stream,myClass[i]);
24
}
25
stream.Close();
26
27
//
反序列化过程开始
28
IFormatter formatter11
=
new
BinaryFormatter();
29
Stream fs
=
new
FileStream(fileName, FileMode.Open, FileAccess.Read,FileShare.Read);
30
long
ii
=
fs.Length;
31
System.Collections.ArrayList list
=
new
System.Collections.ArrayList();
32
//
从文件中逐个读出Class2的实例并反序列化
33
while
(fs.Position
!=
fs.Length)
34
{
35
list.Add(formatter11.Deserialize(fs));
36
}
37
fs.Close();
38
Console.WriteLine(
"
反序列化结果:
"
);
39
foreach
(
object
o
in
list)
40
{
41
Class2 class2
=
o
as
Class2;
42
if
(class2
!=
null
)
43
{
44
Console.WriteLine(
"
名字=
"
+
class2.Name );
45
Console.WriteLine(
"
账号=
"
+
class2.Account.ToString());
46
}
47
}
48
49
Console.ReadLine();
50
}
51
}
52
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52


其实数组也是可以序列化的类
那么我们可以把上面的代码做些简化
1
using
System;
2
using
System.IO;
3
using
System.Runtime.Serialization;
4
using
System.Runtime.Serialization.Formatters.Binary;
5
using
System.Runtime.Serialization.Formatters.Soap;
6
7
namespace
SerializTest
8
{
9
class
Class1
10
{
11
[STAThread]
12
static
void
Main(
string
[] args)
13
{
14

2

3

4

5

6

7

8

9

10

11

12

13

14
