C#对象序列化(1)

对象序列化在应聘过程中并不常见,但是在实际应用中却是很常见的。本节将列举3个比较典型的问题,以扩充.Net的相关知识面。

面试例题20:编写对象序列化的程序。

考点:掌握对象序列化的基本方法,理解序列化中不同格式的区别。

出现频率:★★★

解答

在Visual Studio 2005/Visual Studio 2008中创建一个C#的Windows窗体应用程序项目,并将其项目命名为MultiSerialize。程序使用5个"TextBox"控件分别接受用户的输入,其中上面4个控件用于传递相应的值给某个对象,而下面的"TextBox"控件用于存储文件名。当用户单击"TextBox"操作下面的3个按钮控件中任意一个时,程序将根据用户输入值初始化一组对象,并将对象图进行相应格式的序列化。在Visual Studio 2005/ Visual Studio 2008的"Form1.cs[设计]"视图中创建基本的窗体布局和控件,控件的命名如图7.43所示。

 

 
图7.43  对象序列化窗体控件的布局及命名
在编写代码前,先引用System.Runtime.Serialization. Formatters.Soap.dll程序集,即单击Visual Studio 2005/ Visual Studio 2008菜单栏的"项目|添加引用"命令,在".NET"选项卡中找到所需要的程序集,单击"确定"按钮,即完成了外部程序集的引用操作,结果如图7.44所示。
 
图7.44  引用外部程序集


分别双击Form1的3个按钮控件,编写相应的"Click"事件处理方法。MultiSerialize项目的Form1.cs如代码7.25所示。

代码7.25  序列化对象:Form1.cs

using System;
………………………………………
//导入必要的命名空间
using System.Xml.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Runtime.Serialization;
using System.IO;

 

namespace MultiSerialize
{
public partial class Form1 : Form
{
//声明string类型变量,用于方法中存储用户输入值
string n, nn, p, m, fn, Success;
public Form1()
{
InitializeComponent();
}

 

private void XmlBtn_Click(object sender, EventArgs e)
{
//将用户输入值赋值给变量
n = this.Nm.Text;
nn = this.NNm.Text;
p = this.Pwd.Text;
m = this.Msg.Text;
fn = this.FileName.Text;
//定义成功信息
Success = "XML输出成功";
//创建PersonName的对象引用Pn,并传递4个变量
PersonName Pn = new PersonName(n, nn, p, m);
//创建XmlSerializer的对象引用Xs,并传递类型参数
XmlSerializer Xs = new XmlSerializer(typeof(PersonName), new Type[] { typeof(PersonOther) });
//创建Stream类型引用fs,并传递fn作路径参数
Stream fs = new FileStream(fn, FileMode.Create, FileAccess.Write, FileShare.None);
//调用Xs的Serialize方法,传递fs和Pn参数
Xs.Serialize(fs, Pn);
//关闭fs对象
fs.Close();
//输出成功信息
MessageBox.Show(Success);
}

 

private void BinBtn_Click(object sender, EventArgs e)
{
//创建IFormatter接口引用,来自于BinaryFormatter类对象
IFormatter Fmt = new BinaryFormatter();
//定义成功信息
Success = "二进制输出成功";
//调用UseIFormatter方法,并传递Fmt和Success参数
UseIFormatter(Fmt, Success);
}

 

private void SoapBtn_Click(object sender, EventArgs e)
{
//创建IFormatter接口引用,来自于SoapFormatter类对象
IFormatter Fmt = new SoapFormatter();
//定义成功信息
Success = "Soap输出成功";
//调用UseIFormatter方法,并传递Fmt和Success参数
UseIFormatter(Fmt, Success);
}
//定义UseIFormatter方法,接收一个IFormatter类型参数
void UseIFormatter(IFormatter Fmt, string Success)
{
//将用户输入值赋值给变量
n = this.Nm.Text;
nn = this.NNm.Text;
p = this.Pwd.Text;
m = this.Msg.Text;
fn = this.FileName.Text;
//创建PersonName的对象引用Pn,并传递4个变量
PersonName Pn = new PersonName(n, nn, p, m);
//创建Stream类型引用fs,并传递fn作路径参数
Stream fs = new FileStream(fn, FileMode.Create, FileAccess.Write, FileShare.None);
//调用Fmt的Serialize方法,传递fs和Pn参数
Fmt.Serialize(fs, Pn);
//关闭fs对象
fs.Close();
//输出成功信息
MessageBox.Show(Success);
}
}

 

//定义PersonName类,并标记可序列化特性
[Serializable]
public class PersonName
{
public string _name;
//标记不可序列化特性
[NonSerialized]
public string _nickname;
//创建PersonOther类型的对象Po
public PersonOther Po = new PersonOther();
public PersonName() { }
//重载构造函数,接收4个string类型参数
public PersonName(string n,string nn, string p, string m)
{
//赋值给字段
this._name = n;
this._nickname = nn;
//赋值给Po对象的两个属性
this.Po.Password = p;
this.Po.Message = m;
}
}

 

//定义PersonOther类,并标记可序列化特性
[Serializable]
public class PersonOther
{
//定义2个私有字段
string _password;
string _message;
//定义两个公共属性,可以读写相应的私有字段
public string Password
{
get
{
return _password;
}
set
{
_password = value;
}
}
public string Message
{
get
{
return _message;
}
set
{
_message = value;
}
}
public PersonOther() { }
}
}

程序运行时,可以向前4个"TextBox"控件填入某人的基本资料,然后在Name属性为"FileName"控件中填入"Person.dat",即输出文件的文件名,运行结果如图7.45所示。

当用户单击"二进制格式"按钮后,程序将根据用户输入的值创建并初始化1个PersonName类的对象。程序使用二进制格式序列化该对象并输出到程序集相同目录下的Person.dat文件中,当完成了这些工作,程序将使用信息对话框提示序列化操作成功,运行结果如图7.46所示。

 
图7.45  输入多个信息
 
(点击查看大图)图7.46  以二进制格式序列化
在图7.47中,编译完成的MultiSerialize程序集相同目录下已经创建了Person.dat文件,并且程序也跳出了信息对话框,并提示操作成功。如果按下"Soap格式"按钮或"XML格式"按钮,其运行结果是相似的,但是建议其生成文件的扩展名应分别修改为对应的"soap"和"xml"。假设用户已经生成了3种不同格式的文件,对象数据通过序列化操作持久化到文件中了。用Visual Studio 2005/Visual Studio 2008打开"Person.dat"文件如图7.47所示。
 
(点击查看大图)图7.47  "Person.dat"文件内容
其中中文部分无法正常显示,但是数字是可以正常显示,这是因为Name属性中"Pwd"的控件的值是数字(即图中的"1900")。在程序运行时填入英文,同样可以正常显示。从"Person.dat"文件的内容中可以看出,二进制格式保存了比较完整的对象信息,如所属程序集,程序集版本等信息,有利于以后还原对象数据。用Visual Studio 2005/Visual Studio 2008打开"Person.soap"文件,结果如图7.48所示。
 
(点击查看大图)图7.48  "Person.soap"文件内容
从图7.48中可看到_nickname字段并没有被持久化,因为该字段在Person类中定义时标记了[NonSerialized]特性,即不可序列化。相应地,用Visual Studio 2005/ Visual Studio 2008打开"Person.xml"文件,结果如图7.49所示
 
(点击查看大图)图7.49  "Person.xml"文件内容


说明:项目所生成的程序集路径为"项目路径\bin\debug"。

如果修改程序的代码,可知二进制格式序列化的文件除了保存程序集的信息,还保存私有字段及公共字段的数据SOAP格式和XML格式仅保存对象的公共字段及公共属性,但是这两种格式可以应用于更大范围的平台、应用程序框架中。并且XML格式所序列化的对象数据包含了被标记为[NonSerialized]特性的字段。

说明:本题程序采用IFormatter接口实现多态的应用,使二进制格式化和SOAP格式化操作重用了部分的代码。程序中使用IFormatter接口必须导入其命名空间,即System.Runtime.Serialization。

posted @ 2009-11-22 20:31  杨子宜  阅读(308)  评论(0编辑  收藏  举报