zoukankan      html  css  js  c++  java
  • C#对象序列化(2)

    C#对象序列化(2)
    作者: 日期:2009-3-14 23:42:29 出处:淘特网

    解析

    对象序列化可以使对象的数据持久地保存,对象状态可以是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 自定义序列化窗体控件布局及命名
  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 81.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 40怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 24.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 21.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器试运行提示过速度保护怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器如何执行绝对值清零
    倍福TwinCAT(贝福Beckhoff)基础教程 松下绝对值驱动器如何做初始化设置
    倍福TwinCAT(贝福Beckhoff)基础教程 松下官方软件开启报错伺服未就绪怎么办
    JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
  • 原文地址:https://www.cnblogs.com/zhangq723/p/1707240.html
Copyright © 2011-2022 走看看