C#基础篇-要点(对象序列化)

地址:http://www.cnblogs.com/zhangq723/archive/2010/04/08/1707239.html

对象序列化在应聘过程中并不常见,但是在实际应用中却是很常见的。本节将列举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 @ 2017-11-30 14:36  JackYgy  阅读(159)  评论(0)    收藏  举报