zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    去掉python的警告
    LeetCode--687. 最长同值路径
    Python中获取字典中最值对应的键
    python -- 解决If using all scalar values, you must pass an index问题
    keras自定义padding大小
    评价指标的局限性、ROC曲线、余弦距离、A/B测试、模型评估的方法、超参数调优、过拟合与欠拟合
    一言难尽的js变量提升
    vue-cli 脚手架 安装
    十分钟入门 Less
    Echarts的资源文件
  • 原文地址:https://www.cnblogs.com/jordan2009/p/1632146.html
Copyright © 2011-2022 走看看