刚开始接触.NET的序列化时,完全不知道是什么东西,一脸茫然,在学习中,看到有人直接加一个[Serialization],然后说这是序列化的表示,顿时震惊了,这是什么?后来在图灵丛书的精通C#书中学习到了这是C#的一种特性,其目的是将对象持久化为二进制格式。比如以接下来这个案例作为学习:
/// /// 系统配置实体类 /// [Serializable] public class SysConfig { public int COMno { get; set; } public double VolValue { get; set; } public double CurrentValue { get; set; } public int EquipmentId { get; set; } }
此处在整个类的前面加上了[Serialization]代表着将整个类可以进行序列化成二进制格式如果不想对其中的某一属性或方法序列化,可以在该属性或方法前加上[nonSerialized]标识,这样一来只有该被指定的不会被序列化了,我们设置了四个属性,分别代表了端口号,电流值,电压值,及设备号。这是在工控开发中较为常见的配置。
在窗口相关代码下看其操作方式:
目的是很明确的,将信息持久化的保存在文件中,对于两种形式的保存方式也将体现出序列化的与众不同。
public partial class FrmConfig : Form { SysConfig objSysConfig = null; public FrmConfig() { InitializeComponent(); } /// 文本方式保存信息 /// /// /// /// private void btnTextToSave_Click(object sender, EventArgs e) { objSysConfig = new SysConfig() { COMno = Convert.ToInt32(this.txtCOMno.Text.Trim()), CurrentValue = Convert.ToDouble(this.txtCurrent.Text.Trim()), EquipmentId = Convert.ToInt32(this.txtEquipmentId.Text.Trim()), VolValue = Convert.ToDouble(this.txtVol.Text.Trim()) }; //【1】创建文件流对象 FileStream fs = new FileStream("SysConfigText.obj", FileMode.Create); //【2】创建读写器(写) StreamWriter sw = new StreamWriter(fs); //【3】写入文件 sw.WriteLine(objSysConfig.COMno); sw.WriteLine(objSysConfig.CurrentValue); sw.WriteLine(objSysConfig.EquipmentId); sw.WriteLine(objSysConfig.VolValue); //【4】关闭读写器 sw.Close(); //【5】关闭文件流对象 fs.Close(); } /// 文本方式读取信息 /// /// /// /// private void btnTextToRead_Click(object sender, EventArgs e) { //【1】创建文件流对象 FileStream fs = new FileStream("SysConfigText.obj", FileMode.Open); //【2】创建读写器(读) StreamReader sr = new StreamReader(fs); //【3】读取文件 objSysConfig = new SysConfig() { COMno =Convert.ToInt32(sr.ReadLine()), CurrentValue =Convert.ToDouble(sr.ReadLine()), EquipmentId =Convert.ToInt32(sr.ReadLine()), VolValue =Convert.ToDouble(sr.ReadLine()) }; //【4】关闭读写器 sr.Close(); //【5】关闭文件流对象 fs.Close(); this.txtCOMno.Text = objSysConfig.COMno.ToString(); this.txtVol.Text = objSysConfig.VolValue.ToString(); this.txtEquipmentId.Text = objSysConfig.EquipmentId.ToString(); this.txtCurrent.Text = objSysConfig.CurrentValue.ToString(); } /// 序列化方式保存信息 /// /// /// /// private void btnSeriaToSave_Click(object sender, EventArgs e) { objSysConfig = new SysConfig() { COMno = Convert.ToInt32(this.txtCOMno.Text.Trim()), CurrentValue = Convert.ToDouble(this.txtCurrent.Text.Trim()), EquipmentId = Convert.ToInt32(this.txtEquipmentId.Text.Trim()), VolValue = Convert.ToDouble(this.txtVol.Text.Trim()) }; //【1】创建文件流对象 FileStream fs = new FileStream("SysConfigSeria.obj", FileMode.Create); //【2】创建二进制格式化器 BinaryFormatter bf = new BinaryFormatter(); //【3】调用序列化方法,信息序列化 bf.Serialize(fs, objSysConfig); //【4】关闭文件流 fs.Close(); } /// 序列化方式读取信息 /// /// /// /// private void btnDeseriaToRead_Click(object sender, EventArgs e) { //【1】创建文件流对象 FileStream fs = new FileStream("SysConfigSeria.obj", FileMode.Open); //【2】创建二进制格式化器 BinaryFormatter bf = new BinaryFormatter(); //【3】调用反序列化方法,信息反序列化 objSysConfig = (SysConfig)bf.Deserialize(fs); //【4】关闭文件流 fs.Close(); this.txtCOMno.Text = objSysConfig.COMno.ToString(); this.txtVol.Text = objSysConfig.VolValue.ToString(); this.txtEquipmentId.Text = objSysConfig.EquipmentId.ToString(); this.txtCurrent.Text = objSysConfig.CurrentValue.ToString(); } } }
对于序列化方式中,binaryFormatter这个类是最关键的,其中的Serialize()和Deserialize()方法是序列化学习的关键所在,Serialize()方法通过给它一个文件流参数,相当于给定了笔和纸,再来一个参数是要序列化的对象,相当于要书写的信息,而反序列化就是将写好的作品在通过笔和纸在写回来而这次是看着那些写好的信息在写一份信息出来并且用一个容器保存这些信息,总而言之,言而总之,序列化可以想象成将一个对象转换成二进制形式保存,然后在将这些二进制对象封装,又可以变回一个对象的过程。
这比文本文件的好处在于,在文件中序列化是以二进制方式保存,十分难看懂,而文本文件是以明文形式保存,并且在处理过程上,文本文件方式更见繁琐,但是不是说文本文件毫无用处,比如说写日志文件,你用序列化它那对自己直接面对日志文件而言,毫无疑问是一种相当愚蠢的方式,说的虽然严重了,但是主要是想表达我们不是说为了序列化而序列化文件,一种刻意为之的方式去使用。而是说当我们需要使用的时候,就用,不要强求,一般在项目开发中,针对于实体类而言,我们通常是先加上[Serialization]的,以便更好的应对项目的需求。
这里的运行结果不做展示了,实践出真知,不写一些练手的代码,学习就会太过于枯噪乏味了,学无止境,代码的路还很长。