你的位置:首页 > ASP.net教程

[ASP.net教程]C#对象序列化与反序列化zz


 

C#对象序列化与反序列化(转载自:http://www.cnblogs.com/LiZhiW/p/3622365.html)

1. 对象序列化的介绍.................................................................... 2

(1) .NET支持对象序列化的几种方式................................. 2

(2) 几种序列化的区别............................................................ 2

(3) 使用特性对序列化的控制............................................... 2

2. 使用二进制序列化和反序列化............................................... 2

(1) 二进制序列化与反序列化的程序示例.......................... 2

(2) 总结..................................................................................... 3

3. 使用SOAP方式序列化和反序列化........................................ 3

(1) SOAP序列化与反序列化的程序示例............................. 3

(2) 总结..................................................................................... 4

4. 使用

(1)

(2) 总结..................................................................................... 5

5.

(1) 说明..................................................................................... 5

(2) 使用

(3) 使用

(4) 使用

(5) 使用

(6) 列表和数组的序列化........................................................ 6

(7) 列表和数组的做为数据成员的序列化.......................... 7

(8) 类型继承与反序列化........................................................ 9

(9) 排除不需要序列化的成员............................................. 10

(10) 强制指定成员的序列化顺序....................................... 10

(11) 自定义序列化行为........................................................ 11

(12) 序列化设置

(13)

(14) 反序列化的使用总结................................................... 12

6. 自定义序列化(仅适用于二进制与SOAP).......................... 12

(1) 自定义序列化的实现方式............................................. 12

(2) 示例程序.......................................................................... 12

1.对象序列化的介绍

(1).NET支持对象序列化的几种方式

二进制序列化:对象序列化之后是二进制形式的,通过BinaryFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Binary命名空间下。

SOAP序列化:对象序列化之后的结果符合SOAP协议,也就是可以通过SOAP 协议传输,通过System.Runtime.Serialization.Formatters.Soap命名空间下的SoapFormatter类来实现的。

序列化:对象序列化之后的结果是

(2)几种序列化的区别

二进制格式和SOAP格式可序列化一个类型的所有可序列化字段,不管它是公共字段还是私有字段。

使用二进制格式序列化时,它不仅是将对象的字段数据进行持久化,也持久化每个类型的完全限定名称和定义程序集的完整名称(包括包称、版本、公钥标记、区域性),这些数据使得在进行二进制格式反序列化时亦会进行类型检查。SOAP格式序列化通过使用

(3)使用特性对序列化的控制

要让一个对象支持.Net序列化服务,用户必须为每一个关联的类加上[Serializable]特性。如果类中有些成员不适合参与序列化(比如:密码字段),可以在这些域前加上[NonSerialized]特性。

2.使用二进制序列化和反序列化

(1)二进制序列化与反序列化的程序示例

    [Serializable]  //必须添加序列化特性

    public class Person

    {

        private string Name;//姓名

        private bool Sex;//性别,是否是男

        public Person(string name, bool sex)

        {

            this.Name = name;

            this.Sex = sex;

        }

        public override string ToString()

        {

            return "姓名:" + this.Name + "\t性别:" + (this.Sex ? "男" : "女");

        }

    }

    [Serializable]  //必须添加序列化特性

    public class Programmer : Person

    {

        private string Language;//编程语言

        public Programmer(string name, bool sex, string language) : base(name, sex)

        {

            this.Language = language;

        }

        public override string ToString()

        {

            return base.ToString() + "\t编程语言:" + this.Language;

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            //创建Programmer列表,并添加对象

            List<Programmer> list = new List<Programmer>();

            list.Add(new Programmer("李志伟", true, "C#"));

            list.Add(new Programmer("Coder2", false, "C++"));

            list.Add(new Programmer("Coder3", true, "Java"));

            //使用二进制序列化对象

            string fileName = @"D:\users\lizw\桌面\Programmers.dat";//文件名称与路径

            Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);

            BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器

            binFormat.Serialize(fStream, list);

            //使用二进制反序列化对象

            list.Clear();//清空列表

            fStream.Position = 0;//重置流位置

            list = (List<Programmer>)binFormat.Deserialize(fStream);//反序列化对象

            foreach (Programmer p in list)

            {

                Console.WriteLine(p);

            }

            Console.Read();

        }

    }

(2)总结

使用二进制序列化,必须为每一个要序列化的的类和其关联的类加上[Serializable]特性,对类中不需要序列化的成员可以使用[NonSerialized]特性。

二进制序列化对象时,能序列化类的所有成员(包括私有的),且不需要类有无参数的构造方法。

使用二进制格式序列化时,它不仅是将对象的字段数据进行持久化,也持久化每个类型的完全限定名称和定义程序集的完整名称(包括包称、版本、公钥标记、区域性),这些数据使得在进行二进制格式反序列化时亦会进行类型检查。所以反序列化时的运行环境要与序列化时的运行环境要相同,否者可能会无法反序列化成功。

3.使用SOAP方式序列化和反序列化

(1)SOAP序列化与反序列化的程序示例

    [Serializable]  //必须添加序列化特性

    public class Person

    {

        private string Name;//姓名

        private bool Sex;//性别,是否是男

        public Person(string name, bool sex)

        {

            this.Name = name;

            this.Sex = sex;

        }

        public override string ToString()

        {

            return "姓名:" + this.Name + "\t性别:" + (this.Sex ? "男" : "女");

        }

    }

    [Serializable]  //必须添加序列化特性

    public class Programmer : Person

    {

        private string Language;//编程语言

        public Programmer(string name, bool sex, string language) : base(name, sex)

        {

            this.Language = language;

        }

        public override string ToString()

        {

            return base.ToString() + "\t编程语言:" + this.Language;

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            //实例化对象

            Programmer p = new Programmer("李志伟", true, "C、C#、C++、Java");

            //使用SOAP序列化对象

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);

            SoapFormatter soapFormat = new SoapFormatter();//创建SOAP序列化器

            soapFormat.Serialize(fStream, p);//SOAP不能序列化泛型对象

            //使用SOAP反序列化对象

            fStream.Position = 0;//重置流位置

            p = null;

            p = (Programmer)soapFormat.Deserialize(fStream);

            Console.WriteLine(p);

            Console.Read();

        }

    }

(2)总结

SOAP序列化与二进制序列化的区别是:SOAP序列化不能序列化泛型类型。与二进制序列化一样在序列化时不需要向序列化器指定序列化对象的类型。而

4.使用

(1)

    public class Person

    {

        public string Name;//姓名

        public bool Sex;//性别,是否是男

        public Person() { }//必须提供无参构造器,否则

        public Person(string name, bool sex)

        {

            this.Name = name;

            this.Sex = sex;

        }

        public override string ToString()

        {

            return "姓名:" + this.Name + "\t性别:" + (this.Sex ? "男" : "女");

        }

    }

    public class Programmer : Person

    {

        public string Language;//编程语言

        public Programmer() { }//必须提供无参构造器,否则

        public Programmer(string name, bool sex, string language) : base(name, sex)

        {

            this.Language = language;

        }

        public override string ToString()

        {

            return base.ToString() + "\t编程语言:" + this.Language;

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            //创建Programmer列表,并添加对象

            List<Programmer> list = new List<Programmer>();

            list.Add(new Programmer("李志伟", true, "C#"));

            list.Add(new Programmer("Coder2", false, "C++"));

            list.Add(new Programmer("Coder3", true, "Java"));

            //使用

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);

           

typeof(List<Programmer>),

new Type[] { typeof(Programmer),typeof(Person) }

);//创建

           

            //使用

            fStream.Position = 0;//重置流位置

            list.Clear();

            list = (List<Programmer>)

            foreach (Programmer p in list)

            {

                Console.WriteLine(p);

            }

            Console.Read();

        }

    }

(2)总结

使用

[Serializable]和[NonSerialized]特性对

5.序列化对象详解

(1)说明

本节主要介绍:使用特性控制对象序列化成

(2)使用

类声明:

    public class Person

    {

        [

        public string Name;//使用[

        public bool Sex;//默认使用了[

        public Person() { }//必须提供无参构造器,否则

    }

序列化生成的

<Person

  <Name>李志伟</Name>

  <Sex>true</Sex>

</Person>

(3)使用

类声明:

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

序列化生成的

<Person

  <Name>李志伟</Name>

</Person>

(4)使用

类声明:

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

序列化生成的

<Person

(5)使用

类声明:

    [

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

序列化生成的

<个人信息

(6)列表和数组的序列化

类声明:

    [

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

    class Program

    {

        static void Main(string[] args)

        {

            Person p = new Person();

            p.Name = "李志伟";

            p.Sex = true;

            Person[] ps = new Person[3];

            ps[0] = p;

            ps[1] = p;

            ps[2] = p;

            //使用

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create);

           

           

            fStream.Dispose();//关闭文件

            Console.WriteLine("OK!");

            Console.Read();

        }

    }

序列化生成的

<ArrayOf个人信息

  <个人信息姓名="李志伟"性别="true" />

  <个人信息姓名="李志伟"性别="true" />

  <个人信息姓名="李志伟"性别="true" />

</ArrayOf个人信息>

注意:发现此时的

    [

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

    [

    public class PersonArray : List<Person> { }

    class Program

    {

        static void Main(string[] args)

        {

            Person p = new Person();

            p.Name = "李志伟";

            p.Sex = true;

            PersonArray ps = new PersonArray();

            ps.Add(p);

            ps.Add(p);

            ps.Add(p);

            //使用

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create);

           

           

            fStream.Dispose();//关闭文件

            Console.WriteLine("OK!");

            Console.Read();

        }

    }

序列化生成的

<人员信息

  <个人信息姓名="李志伟"性别="true" />

  <个人信息姓名="李志伟"性别="true" />

  <个人信息姓名="李志伟"性别="true" />

</人员信息>

(7)列表和数组的做为数据成员的序列化

类声明:

    [

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

    public class PersonArray

    {

        public List<Person> Array=new List<Person>();

        public Person Person = new Person();

    }

    class Program

    {

        static void Main(string[] args)

        {

            PersonArray ps = new PersonArray();

            ps.Person = new Person();

            ps.Person.Name = "李志伟";

            ps.Person.Sex = true;

            ps.Array.Add(ps.Person);

            ps.Array.Add(ps.Person);

            ps.Array.Add(ps.Person);

            //使用

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create);

           

           

            fStream.Dispose();//关闭文件

            Console.WriteLine("OK!");

            Console.Read();

        }

    }

序列化生成的

<PersonArray

  <Array>

    <个人信息姓名="李志伟"性别="true" />

    <个人信息姓名="李志伟"性别="true" />

    <个人信息姓名="李志伟"性别="true" />

  </Array>

  <Person姓名="李志伟"性别="true" />

</PersonArray>

注意:假设这里需要为Array和Person的节点重命名,代码如下:

    [

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

    public class PersonArray

    {

        [

        [

        public List<Person> Array=new List<Person>();

        public Person Person = new Person();

    }

序列化生成的

<PersonArray

  <人员信息>

    <个人信息姓名="李志伟"性别="true" />

    <个人信息姓名="李志伟"性别="true" />

    <个人信息姓名="李志伟"性别="true" />

  </人员信息>

  <Person姓名="李志伟"性别="true" />

</PersonArray>

注意:把“人员信息”节点去掉呢(直接出现“个人信息”节点)

    [

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

    public class PersonArray

    {

        [

        public List<Person> Array=new List<Person>();

        public Person Person = new Person();

    }

序列化生成的

<PersonArray

  <个人信息姓名="李志伟"性别="true" />

  <个人信息姓名="李志伟"性别="true" />

  <个人信息姓名="李志伟"性别="true" />

  <Person姓名="李志伟"性别="true" />

</PersonArray>

(8)类型继承与反序列化

类声明:

    public class Base { }

    [

    public class PersonA : Base

    {

        [

        public string Name;

        [

        public bool Sex;

        public PersonA() { }//必须提供无参构造器,否则

    }

    [

    public class PersonB : Base

    {

        [

        public string Name;

        [

        public int Age;

        public PersonB() { }//必须提供无参构造器,否则

    }

    [

    public class PersonArray

    {

        [

        public List<Base> ListPerson=new List<Base>();

    }

    class Program

    {

        static void Main(string[] args)

        {

            PersonA pa = new PersonA();

            pa.Name = "李志伟A";

            pa.Sex = true;

            PersonB pb = new PersonB();

            pb.Name = "李志伟B";

            pb.Age = 21;

            PersonArray ps = new PersonArray();

            ps.ListPerson.Add(pa);

            ps.ListPerson.Add(pa);

            ps.ListPerson.Add(pb);

            ps.ListPerson.Add(pb);

            //使用

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create);

           

           

            fStream.Dispose();//关闭文件

            Console.WriteLine("OK!");

            Console.Read();

        }

    }

序列化生成的

<人员信息

  <ListPerson>

    <信息A姓名="李志伟A"性别="true" />

    <信息A姓名="李志伟A"性别="true" />

    <信息B>

      <姓名>李志伟B</姓名>

      <年龄>21</年龄>

    </信息B>

    <信息B>

      <姓名>李志伟B</姓名>

      <年龄>21</年龄>

    </信息B>

  </ListPerson>

</人员信息>

注意:同时为列表成员指定多个[

(9)排除不需要序列化的成员

类声明:

    public class Person

    {

        public string Name;

        [

        public bool Sex;

        public Person() { }

    }

序列化生成的

<Person

  <Name>李志伟</Name>

</Person>

(10)强制指定成员的序列化顺序

类声明:

    public class Person

    {

        [

        public string Name;

        [

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

    }

序列化生成的

<Person

  <Sex>true</Sex>

  <Name>李志伟</Name>

</Person>

(11)自定义序列化行为

类声明:

    public class Person : I

    {

        public string Name;

        public bool Sex;

        public Person() { }//必须提供无参构造器,否则

        public System.

        {

            return null;

        }

        public void Read

        {

            Name = reader.GetAttribute("姓名");

            Sex = reader.GetAttribute("性别").Equals("男") ? true : false;

        }

        public void Write

        {

            writer.WriteAttributeString("姓名", Name);

            writer.WriteAttributeString("性别", Sex ? "男" : "女");

        }

    }

序列化生成的

<Person姓名="李志伟"性别="男" />

(12)序列化设置

类声明:

    [

    public class Person

    {

        public string Name;

        public bool Sex;

        public Person() { }

    }

序列化生成的

<Person

  <Name>李志伟A</Name>

  <Sex>true</Sex>

</Person>

(13)

在服务端,C#代码中:

1. 建议不用使用低级别的

2. 建议使用序列化、反序列化的方法来生成或者读取

3. 当需要考虑使用

4. 列表节点不要使用[

5. 如果希望序列化的

6. 不要在一个列表中输出不同的数据类型,这样的

7. 尽量使用UTF-8编码,不要使用GB2312编码。

在客户端,JavaScript代码中,我不建议使用

1.

2. 在JavaScritp中使用

(14)反序列化的使用总结

如果

1. 首先要分析整个

2. 如果

3. 定义具体类型(一个层级下的

形式

处理方法

补充说明

定义一个属性

属性名与节点名字匹配

[

InnerText

[InnerText] 加到属性上

一个类型只能使用一次

节点重命名

根节点:[元素节点:[属性节点:[列表子元素节点:[列表元素自身:[

6.自定义序列化(仅适用于二进制与SOAP)

(1)自定义序列化的实现方式

可以通过在对象上实现 ISerializable 接口来自定义序列化过程。这一功能在反序列化后成员变量的值失效时尤其有用,但是需要为变量提供值以重建对象的完整状态。要实现ISerializable,需要实现 GetObjectData()方法以及一个特殊的构造函数,在反序列化对象时要用到此构造函数。

(2)示例程序

    [Serializable]

    public class Person : ISerializable

    {

        public string Name;

        public bool Sex;

        public Person() { }

        //必须的够着方法,反序列化时调用

        protected Person(SerializationInfo info, StreamingContext context)

        {

            Name = info.GetString("姓名");

            Sex = info.GetBoolean("性别");

        }

        //序列化时调用

        public void GetObjectData(SerializationInfo info, StreamingContext context)

        {

            info.AddValue("姓名", Name + "(自定义序列化)");

            info.AddValue("性别", Sex);

        }

        public override string ToString()

        {

            return "姓名:" + this.Name + "\t性别:" + (this.Sex ? "男" : "女");

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Person p = new Person();

            p.Name = "李志伟A";

            p.Sex = true;

            //使用二进制序列化对象

            string fileName = @"D:\users\lizw\桌面\Programmers.

            Stream fStream = new FileStream(fileName, FileMode.Create);

            BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器

            binFormat.Serialize(fStream, p);//序列化对象

            //使用二进制反序列化对象

            fStream.Position = 0;//重置流位置

            p = (Person)binFormat.Deserialize(fStream);//反序列化对象

            Console.WriteLine(p);

            fStream.Dispose();//关闭文件

            Console.WriteLine("OK!");

            Console.Read();

        }

    }

注意:在序列化过程中调用 GetObjectData()时,需要填充方法调用中提供的SerializationInfo对象。只需按名称/值对的形式添加将要序列化的变量。其名称可以是任何文本。只要已序列化的数据足以在反序列化过程中还原对象,便可以自由选择添加至SerializationInfo 的成员变量。如果基对象实现了 ISerializable,则派生类应调用其基对象的 GetObjectData()方法。同样,在反序列化时也会调用含有(SerializationInfo info, StreamingContextcontext)参数的特殊的够着方法!否者将无法反序列化!!!