相关文章导航
Sql Server2005 Transact-SQL 新兵器学习总结之-总结
Flex,Fms3相关文章索引
FlexAir开源版-全球免费多人视频聊天室,免费网络远程多人视频会议系统((Flex,Fms3联合开发))<视频聊天,会议开发实例8>
我最近学习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
说明:
序列化一个类的最简单的方式是使用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 }
结果是
我们可以看到由于类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 }
结果是
其实数组也是可以序列化的类
那么我们可以把上面的代码做些简化
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 IFormatter formatter = new BinaryFormatter(); 19 Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write,FileShare.None); 20 formatter.Serialize(stream,myClass);21 stream.Close();22 23 // 反序列化过程开始 24 IFormatter formatter11 = new BinaryFormatter(); 25 Stream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read,FileShare.Read); 26 Class2[] list= (Class2[])formatter11.Deserialize(fs); 27 fs.Close();28 Console.WriteLine(" 反序列化结果: " ); 29 foreach (Class2 o in list) 30 { 31 Console.WriteLine(" 名字= " + o.Name ); 32 Console.WriteLine(" 账号= " + o.Account.ToString()); 33 }34 35 Console.ReadLine();36 }37 }38 }
代码简化了不少,功能是一样的 小总结: 我上面的代码全部是利用了BinaryFormatter类来进行序列化 此类序列化对于在 .NET 平台上进行运用效果比较理想 要是考虑到程序的可移植性,我们可以考虑用类SoapFormatter替代 同样也是调用Serialize和Deserialize方法 因为这2个类都实行了接口IFormatter 特别注意的是,Serializable属性不能被继承. 由SerializableAttribute类的定义我们可以看出. [AttributeUsage(AttributeTargets.Delegate | (AttributeTargets.Enum | (AttributeTargets.Struct | AttributeTargets.Class)), Inherited=false)] public sealed class SerializableAttribute : Attribute 如果我们从Class2派生一个新类,此新类必须也用该属性标记,否则它不能被序列化.
希望上面提到的知识对你有所提示
当然欢迎交流和指正
收藏与分享
收藏到QQ书签 添加到百度搜藏 添加到雅虎收藏
东莞.net俱乐部
欢迎您的加入