• C#对象序列化(2)


    解析

    对象序列化可以使对象的数据持久地保存,对象状态可以是Ssytem.IO.Stream的派生类型。并不是任何类型的对象都可以被序列化的,只有当其类型定义为可序列化时,该对象才可以被序列化。例如,自定义一个类类型,当该类类型被标记了[Serializable]特性后,其对象即可被序列化。序列化的代码本身很简单,并可使用多种格式保存对象(或对象图),如二进制格式、SOAP格式和XML格式。

    将对象以二进制格式序列化,需要使用BinaryFormatter类型,该类型位于mscorlib.dll程序集,使用时只需导入其命名空间即可,程序代码如以下代码所示:

    //导入BinaryFormatter类的命名空间
    using System.Runtime.Serialization.Formatters.Binary;
    //创建BinaryFormatter类对象MyBF
    BinaryFormatter MyBF = new BinaryFormatter();
    //创建自定义类MyClass的对象引用obj,该类已经标记了[Serializable]特性
    MyClass obj = new MyClass();
    //创建Stream类型引用fs
    Stream fs = new FileStream(需要保存的路径, FileMode.Create,
    FileAccess.Write, FileShare.None);
    //调用MyBF的Serialize方法,传递fs和obj参数
    MyBF.Serialize(fs, Pn);
    //关闭fs对象
    fs.Close();

    可见,只需调用BinaryFormatter类对象的Serialize()方法,即可完成序列化的操作。如果使用SOAP格式序列化,其操作和二进制格式基本一致,只是由SoapFormatter类的对象调用Serialize()方法。由于定义SoapFormatter类的命名空间是System.Runtime. Serialization.Formatters.Soap,而这个命名空间定义于System.Runtime.Serialization. Formatters.Soap.dll程序集内,所以使用SoapFormatter类时,需手动引用该程序集,然后导入该命名空间。实际上,BinaryFormatter类和SoapFormatter类都实现了IFormatter接口,所以在程序应用中,可以编写相应的多态程序。

    XML格式序列化对象需要创建System.Xml.Serialization.XmlSerializer类对象,然后调用Serialize()方法。该类的命名空间虽然定义于System.Xml.dll程序集内,但是Visual Studio 2005/ Visual Studio 2008将自动引用该程序集,所以不需要手动引用System.Xml.dll程序集。XML格式序列化的方法如以下代码所示:

    //导入XmlSerializer类的命名空间
    using System.Xml.Serialization;
    //创建XmlSerializer类对象MyXS
    XmlSerializer MyXS = new XmlSerializer(typeof(MyClass),
    要序列化其他对象的Type类型数组);
    //创建自定义类MyClass的对象引用obj,该类已经标记了[Serializable]特性
    MyClass obj = new MyClass();
    //创建Stream类型引用fs
    Stream fs = new FileStream(需要保存的路径, FileMode.Create,
    FileAccess.Write, FileShare.None);
    //调用MyXS的Serialize方法,传递fs和obj参数
    MyXS.Serialize(fs, Pn);
    //关闭fs对象
    fs.Close();

    XmlSerializer类的构造函数需要传递参数,当只需要实现一个独立对象时,传递该对象所属类的Type对象类型即可,当该对象依赖于其他对象时,需要将其他对象所属类的Type对象类型作为数组传递。

    说明:对象图是指一组关联的对象关系图,描述了多个对象之间的依赖关系。

    面试例题21:如何将XML格式持久化的对象反序列化?

    考点:反序列化的基本方法,处理反序列化后的对象数据。

    出现频率:★★

    解答

    在Visual Studio 2005/ Visual Studio 2008中创建一个C#的Windows窗体应用程序项目,并将其项目命名为ListSerialize。程序序列化的对象是List<T>类的对象(该类是可序列化的),通过"添加"按钮控件,增加List<T>类对象中的子项,直到单击"输出XML"按钮。而单击"XML反序列化"按钮后,指定XML文件中的对象信息还原,并在ListBox控件(命名为"XmlList")中输出该对象的每个子项数据。在Visual Studio 2005/ Visual Studio 2008的"Form1.cs[设计]"视图中创建基本的窗体布局和控件,控件的命名如图7.50所示。

     
    (点击查看大图)图7.50  反序列化程窗体控件布局及命名

    编写ListSerialize项目的Form1.cs如代码7.26所示。

    代码7.26  反序列化对象:Form1.cs

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

    namespace ListSerialize
    {
    public partial class Form1 : Form
    {
    //创建List<T>类型对象list,子项类型为PersonDetail
    List<PersonDetail> list = new List<PersonDetail>();
    //声明List<T>类型readlist变量,子项类型为PersonDetail
    List<PersonDetail> readlist;
    //声明fn变量,用于存储文件路径
    string fn;
    public Form1()
    {
    InitializeComponent();
    }

    private void AddBtn_Click(object sender, EventArgs e)
    {
    //创建PersonDetail类型对象Pd
    PersonDetail Pd = new PersonDetail();
    //将两个文本框控件内容赋值给Pd的两个对象
    Pd.Name = nametxt.Text;
    Pd.Password = passwordtxt.Text;
    //list对象添加子项Pd
    list.Add(Pd);
    MessageBox.Show("添加成功");
    }

    private void OutputBtn_Click(object sender, EventArgs e)
    {
    //获取用户输入的文件路径
    fn = FileName.Text;
    //创建XmlSerializer的对象引用Xs,并传递List<PersonDetail>的类型
    XmlSerializer Xs = new XmlSerializer(typeof(List<PersonDetail>));
    //创建Stream类型引用fs,并传递fn作路径参数
    Stream fs = new FileStream(fn, FileMode.Create, FileAccess.Write, FileShare.None);
    //调用Xs的Serialize方法,传递fs和list参数
    Xs.Serialize(fs, list);
    //关闭fs对象
    fs.Close();
    MessageBox.Show("XML序列化成功");
    //将文本框控件清空
    nametxt.Text = "";
    passwordtxt.Text = "";
    FileName.Text = "";
    }

    private void InputBtn_Click(object sender, EventArgs e)
    {
    string str;
    //获取用户输入的文件路径
    fn = ReadFileName.Text;
    try
    {
    //创建FileStream类型引用fs,并传递fn作路径参数,文件模式为打开文件
    FileStream fs = new FileStream(fn, FileMode.Open);
    //创建XmlSerializer类型对象Xs,传递List<PersonDetail>的类型
    XmlSerializer Xs = new XmlSerializer(typeof(List<PersonDetail>));
    //调用Xs的Deserialize方法,传递fs
    //将返回的对象转换为List<PersonDetail>类型,并将引用赋值给readlist
    readlist = (List<PersonDetail>)Xs.Deserialize(fs);
    //遍历readlist的每个子项
    foreach (PersonDetail Pd in readlist)
    {
    //将子项的属性值组合后赋值给str变量
    str = String.Format("姓名:【{0}】,密码:【{1}】", Pd.Name, Pd.Password);
    //调用XmlList控件Items的Add方法,将str添加为项
    XmlList.Items.Add(str);
    }
    }
    //处理文件未找到异常
    catch (FileNotFoundException ex)
    {
    string msg = String.Format("异常信息:{0}", ex.Message);
    MessageBox.Show(msg);
    }
    //将文件路径文本框控件清空
    ReadFileName.Text = "";
    }
    }

    public class PersonDetail
    {
    //定义两个私有字段
    string _name;
    string _password;
    //定义两个公共属性,可以读写相应的私有字段
    public string Name
    {
    get
    {
    return _name;
    }
    set
    {
    _name = value;
    }
    }
    public string Password
    {
    get
    {
    return _password;
    }
    set
    {
    _password = value;
    }
    }
    public PersonDetail() { }
    }
    }

    程序运行后,在前两个"TextBox"控件中输入一组值并单击"添加"按钮,结果如图7.51所示。

    用户每单击一次"添加"按钮,list对象中将添加一个子项,该子项是根据用户输入值初始化的PersonDetail类的对象。当子项添加操作完成后,程序弹出如图7.51所示的信息对话框。进行多次添加操作后,在Name属性为"ReadFileName"的文本框控件输入任意XML文件的文件名,单击"输出XML"按钮,即可完成XML格式的序列化操作。可将序列化操作创建的XML文件名再次输入到Name属性为ReadFileName的文本框控件中,然后单击"XML反序列化"按钮即可完成该XML文件中数据的反序列化操作,运行结果如图7.52所示。

     
    图7.51  以XML格式序列化
     
    (点击查看大图)图7.52  反序列化XML文件并输出

    根据输入值,创建的list对象数据已经被成功反序列化,并且在Name属性为"XmlList"的列表框控件中显示。

    解析

    反序列化是序列化的逆向操作,既然序列化操作需要写入到流,反序列化即读取流并将对象数据提取出来。例如,在程序集相同目录下有一个"Person.dat"文件,该文件以二进制格式持久化已知类型(如PersonName类)的对象,其反序列化的方法如以下代码所示:

    //导入BinaryFormatter类的命名空间
    using System.Runtime.Serialization.Formatters.Binary;
    //创建BinaryFormatter类对象MyBF
    BinaryFormatter MyBF = new BinaryFormatter();
    //创建FileStream 类型引用fs,读取"Person.dat"文件
    FileStream fs = new FileStream("Person.dat", FileMode.Open);
    //调用MyBF的DeSerialize方法,传递fs参数
    PersonName Pn = (PersonName)MyBF.DeSerialize(fs);
    //关闭fs对象
    fs.Close();

    以上代码中,程序获得了PersonName类对象的引用Pn,该对象根据"Person.dat"文件反序列化创建,还原原对象的数据。

    面试例题22:如何自定义序列化?

    考点:理解自定义序列化,学习自定义序列化方法。

    出现频率:★★★★

    解答

    在Visual Studio 2005/ Visual Studio 2008中创建一个C#的Windows窗体应用程序项目,并将其项目命名为CustomSerialize。程序可以根据用户输入值创建一个对象,以二进制格式序列化对象,并持久化到指定的路径。这个过程,对象的字段值将被添加一段字符串,并且其字段值对应的键名也被修改为指定值,而不是字段名称。在反序列化的过程中,对象的字段数据值被修改为原始值,所以看上去对象数据没有作任何修改。在Visual Studio 2005/Visual Studio 2008的"Form1.cs[设计]"视图中创建基本的窗体布局和控件,控件的命名如图7.53所示。

     
    (点击查看大图)图7.53  自定义序列化窗体控件布局及命名

  • 相关阅读:
    javascript和jquery模拟select框
    CSS使用菱形◆制作气泡对话框(兼容IE6 IE9)
    给网站添加显示在标签页上的小图标
    mysql设置utf8_unicode_ci字符集php页面输出??乱码的解决方法
    推荐一个学习的站
    ubuntu 12.04 安装 nginx+php+mysql web服务器
    PHP解决[function.filegetcontents]: failed to open stream: HTTP request failed!
    svn 操作命令
    svn 端口查看
    php函数parse_url()
  • 原文地址:https://www.cnblogs.com/jordan2009/p/1632149.html
Copyright © 2020-2023  润新知