Serialization全解析

Serialization即序列化,序列化是可被定义为将对象的状态存储到存储媒介中的过程。在此过程中,对象的公共字段和私有字段以及类的名称(包括包含该类的程序集)都被转换为字节流,然后写入数据流。在以后反序列化该对象时,创建原始对象的精确复本。
 
 Remoting和Web Service就是序列化的典型的应用,通过序列化将一个对象从一个应用程序域,发送到另一个应用程序域。
 
 序列化类默认的情况下是要求他的所有的成员都是要可序列化的(除事件、委托、显式定义不可序列化),对于不想被序列化的成员要声明不可序列化把它加上 [NonSerialized]属性告诉.NET这个类不要被序列化,这样在序列化的时候就不会保存对象的状态。
 
 下面就将常用的几种序列化方式一一实现出来给大家看一下!
 
 首先需要新建一个被实例化的类:Person.cs
 
 namespace SerializationTest
 {
     [Serializable]//此属性标记为该类可以实例化
     [XmlRoot("Hello")]//标记为XML文档的根节点名字
     public  class Person<T>
     {
        [XmlAttribute("Name")]/标记为XML文档属性名
       public string Name
        {
            get;
            set;
        }
       [XmlAttribute("Sex")]
       public string Sex
       {
           get;
           set;
       }
       [XmlAttribute("Age")]
       public int Age
       {
           get;
           set;
       }
       [NonSerialized]//此属性标记为不可序列化
       Work w;
       public Work W
       {
           get
           {
               return w;
           }  
           set
           {
               w = value;
           }
       }
     }
      
     public class Work
     {
           [XmlAttribute("WorkName")]
         public string WorkName
         {
             get;
             set;
         }
     }
 
 
 下面开始介绍常使用的几种序列化的方法
 
 一、BinaryFormatter
 
 在使用之前需要先引入命名空间:
 
 using System.Runtime.Serialization;
 using System.Runtime.Serialization.Formatters;
 using System.Runtime.Serialization.Formatters.Binary;
 
 具体的实现方法如下:
 
  //BinaryFormatter方式序列化
         private static void Serializable(Person<Work> p)
         {
             IFormatter formatter = new BinaryFormatter();
             //创建文件流
             Stream stream = new FileStream(@"D:\Persons.bin", FileMode.Create, FileAccess.Write, FileShare.None);
             using (stream)
             {
                 formatter.Serialize(stream, p);
             }
             Console.WriteLine("序列化完成!");
             Console.ReadKey();
             Console.WriteLine("按任意键继续反序列化!");
             Console.ReadKey();
         }
         //BinaryFormatter方式反序列化
         private static void Deserializable()
         {
             Person<Work> p;
             IFormatter formatter = new BinaryFormatter();
             Stream stream = new FileStream(@"D:\Persons.bin", FileMode.Open, FileAccess.Read, FileShare.None);
             using (stream)
             {
                 p = (Person<Work>)formatter.Deserialize(stream);
             }
             if (p.W == null)
             {
                 Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age );
             }
             else
             {
                 Console.WriteLine("Person类的Work属性未被实例化!");
             }
            
         }
 
 
  //BinaryFormatter方式序列化
         private static void Serializable(Person<Work> p)
         {
             IFormatter formatter = new BinaryFormatter();
             //创建文件流
             Stream stream = new FileStream(@"D:\Persons.bin", FileMode.Create, FileAccess.Write, FileShare.None);
             using (stream)
             {
                 formatter.Serialize(stream, p);
             }
             Console.WriteLine("序列化完成!");
             Console.ReadKey();
             Console.WriteLine("按任意键继续反序列化!");
             Console.ReadKey();
         }
         //BinaryFormatter方式反序列化
         private static void Deserializable()
         {
             Person<Work> p;
             IFormatter formatter = new BinaryFormatter();
             Stream stream = new FileStream(@"D:\Persons.bin", FileMode.Open, FileAccess.Read, FileShare.None);
             using (stream)
             {
                 p = (Person<Work>)formatter.Deserialize(stream);
             }
             if (p.W == null)
             {
                 Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age );
             }
             else
             {
                 Console.WriteLine("Person类的Work属性未被实例化!");
             }
            
         }
 
 在Main函数中调用如下
 
  static void Main(string[] args)
         {
             Person<Work> p = new Person<Work>()
             {
                 Name = "Olive",
                 Sex = "female",
                 Age = 22,
                 W = new Work()
                 {
                     WorkName = "Student"
                 }
             };
 
             Serializable(p);      //BinaryFormatter序列化,将对象以二进制流的方式写入本地文件
             Deserializable();     //BinaryFormatter反序列化 ,从本地文件读取二进制流,反序列化为对象
 
 }
 
 执行完之后效果如下:
 
 1、在D盘产生一个Person.bin文件,保存的就是Person对象的属性,
 
 2、反序列化后,可以重新得到对象
 
 
 
 二、SoapFormatter
 
 要序列化成SOAP就要先用引用System.Runtime.Serialization.Formatters.Soap命名空间中的SoapFormatter类。
 
 SoapFormatter是一个Soap的格式器
 
 具体的代码如下:(还是引用开始的Person类)
 
    //SoapFormatter方式序列化
         private static void SoapSerializable(Person p)
         {
             IFormatter formatter = new SoapFormatter();
             Stream stream=new FileStream(@"D:\Person.xml",FileMode.Create,FileAccess.Write,FileShare.None);
             using(stream)
             {
             formatter.Serialize(stream,p);
             }
             Console.WriteLine("SoapSerializable序列化完毕!");
         }
         //SoapFormatter反序列化
         private static void DesoapSerializable()
         {
             Person  p;
             IFormatter formatter = new SoapFormatter();
             Stream stream = new FileStream(@"D:\Person.xml", FileMode.Open, FileAccess.Read, FileShare.None);
             using (stream)
             {
                 p = (Person )formatter.Deserialize(stream);
             }
             Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age);
             Console.WriteLine("SoapSerializable反序列化完毕!");
         }
 
 主函数
 
    static void Main(string[] args)
         {
             Person  p = new Person()
             {
                 Name = "Olive",
                 Sex = "female",
                 Age = 22,
                 W = new Work()
                 {
                     WorkName = "Student"
                 }
             };
 
       SoapSerializable(p); //SoapFormatter序列化,(但是不支持泛型的序列化 )将对象序列化为xml格式的字符串,存入本地.xml文件
             DesoapSerializable(); //SoapFormatter反序列化
 
 }
 
 执行完之后效果如下:
 
 1、在D盘产生一个Person.XML文件,保存的就是Person对象的属性,
 
 2、反序列化后,可以重新得到对象
 
 
 
 三、XmlSerializer
 
 首先需要引入命名空间:System.Xml.Serialization
 
 主要代码如下:
 
 //XMLSerializable序列化
         private static void XMLSerializable(Person<Work> p)
         {
             XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person<Work>));
             Stream stream = new FileStream(@"D:\XMLPerson.xml", FileMode.Create, FileAccess.Write, FileShare.None);
             using (stream)
             {
                 xmlSerializer.Serialize(stream, p);
             }
             Console.WriteLine("XMLSerializable序列化完毕!");
             Console.WriteLine("按任意键继续反序列化!");
             Console.ReadKey();
         }
         //XMLSerializable反序列化
         private static void DeXMLSerializable()
         {
             Person<Work> p;
             XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person<Work>));
             Stream stream = new FileStream(@"D:\XMLPerson.xml", FileMode.Open, FileAccess.Read, FileShare.None);
             using (stream)
             {
                 p = (Person<Work>)xmlSerializer.Deserialize(stream);
             }
             if (p != null)
             {
                 Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age);
                 Console.WriteLine("XMLSerializable反序列化成功!");
 
             }
             else
                 Console.WriteLine("XMLSerializable反序列化失败!");
         }
 
 
 主函数调用如下:
 
 static void Main(string[] args)
         {
             Person<Work> p = new Person<Work>()
             {
                 Name = "Olive",
                 Sex = "female",
                 Age = 22,
                 W = new Work()
                 {
                     WorkName = "Student"
                 }
             };
 
     XMLSerializable(p);   //XMLSerializable序列化 ,将对象序列化为XML格式的字符串
             DeXMLSerializable();  // XMLSerializable序列化
 
 }
 
 执行后效果如下:
 
 1、在D盘产生一个XMLPerson.XML文件,保存的就是Person对象的属性,
 
 2、反序列化后,可以重新得到对象
 
 
 
 
 这里的跟节点之所是Hello而不是Person是因为在Person类中,将Person的类的跟节点标记为
 
 [XmlRoot("Hello")]
     public  class Person<T>{}
 
 同时Work的节点名为W也是这个缘故
 
   [XmlAttribute("WorkName")]
         public string WorkName
         {
             get;
             set;
         }
 
 四、DataContractJsonSerializer(将对象序列化为Json格式的字符串)
 
 在使用前需要添加引用:System.ServiceModel.Web 和 System.Runtime.Serialization,
 
 然后使用
 
 using System.Runtime.Serialization.Json;ITPUB个人空间3htH4O+A.sQ!n
 using System.Runtime.Serialization;
 
 具体代码如下:
 
 
     //SerializableJson 将对象序列化为Json格式字符串
         private static string SerializableJson(Person<Work> p)
         {
             DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Person<Work>));
             using (MemoryStream memory = new MemoryStream())
             {
                 serializer.WriteObject(memory, p);
                 result = UTF8Encoding.Default.GetString(memory.ToArray());
                 Console.WriteLine(result);
             }
             Console.WriteLine("SerializableJson序列化完毕!");
             return result;
         }
         //SerializableJson 将Json格式的字符串序列化为对象
         private static void DeSerializableJson(string jsonString)
         {
             Person<Work> p;
             var serializer = new DataContractJsonSerializer(typeof(Person<Work>));
             using (MemoryStream memory = new MemoryStream(UTF8Encoding.Default.GetBytes(jsonString)))
             {
                 p = (Person<Work>)serializer.ReadObject(memory);
             }
             Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age);
             Console.WriteLine("Json序列化完毕了!");
             Console.WriteLine("按任意键继续");
             Console.ReadKey();
         }
 
 主函数调用
 
 static void Main(string[] args)
         {
             Person<Work> p = new Person<Work>()
             {
                 Name = "Olive",
                 Sex = "female",
                 Age = 22,
                 W = new Work()
                 {
                     WorkName = "Student"
                 }
             };
 
 执行结果如下:
 
 
 
 
 五、DataContactSerializer(可以将对象序列化为Json格式的字符串和XML格式的字符串,为Json格式时,需要在将要序列化的类属性上添加[DataMember]特性,
 
 为XML格式时,需要在将要序列化的类属性上添加[XmlAttribute("属性名")]特性,这样就会根据所添加的特性的不同而生成不同格式的字符串
 
 首先需要添加引用:
 
 using System.ServiceModel;
 
 具体代码如下:(生成JSON格式的字符串)
 
  private static string SerializerDataContract(Person<Work> p)
         {
             DataContractSerializer dataSerializer = new DataContractSerializer(typeof(Person<Work>));
             using (MemoryStream memory = new MemoryStream())
             {
                 dataSerializer.WriteObject(memory, p);
                 result = UTF8Encoding.Default.GetString(memory.ToArray());
                 Console.WriteLine(result);
                 Console.WriteLine("DataContractSerializer序列化完毕!");
             }
             return result;
 
         }
         private static void DeSerializerDataContract(string result)
         {
             Person<Work> p;
             DataContractSerializer dataSerializer = new DataContractSerializer(typeof(Person<Work>));
             using (MemoryStream memory = new MemoryStream(UTF8Encoding.Default.GetBytes(result)))
             {
                 p = (Person<Work>)dataSerializer.ReadObject(memory);
                 Console.WriteLine(p.Name + ":::" + p.Sex + ":::" + p.Age);
             }
         }
 
 主函数调用:
 
         static void Main(string[] args)
         {
             Person<Work> p = new Person<Work>()
             {
                 Name = "Olive",
                 Sex = "female",
                 Age = 22,
                 W = new Work()
                 {
                     WorkName = "Student"
                 }
             };
  SerializerDataContract(p);
             DeSerializerDataContract(result);
 
 }
 
 执行结果如下:
 
 
 
 六、将对象序列化为字符串、或者字节数组
 
 先要引用命名空间
 
 using System.Runtime.Serialization;
 using System.Runtime.Serialization.Formatters;
 using System.Runtime.Serialization.Formatters.Soap;
 using System.Runtime.Serialization.Formatters.Binary;
 
 
 using system.Runtime.
 
 主要代码:
 
        //SerializableString将对象序列化为字符串
         private static string SerializableString(Person<Work> p)
         {
 
             XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person<Work>));
             using (MemoryStream memoryStream = new MemoryStream())
             {
                 xmlSerializer.Serialize(memoryStream, p);
                 result = UTF8Encoding.Default.GetString(memoryStream.ToArray());
                 Console.WriteLine(result);
                 return result;
 
             }
         }
         //将字符串反序列化为对象
         public static void DeSerializableString(string result, Person<Work> p)
         {
             XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person<Work>));
             using (StringReader stringReader = new StringReader(result))
             {
                 p = (Person<Work>)xmlSerializer.Deserialize(stringReader);
             }
             Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age);
             Console.WriteLine("反序列化完毕!");
 
         }
         private static byte[] buffer;
         //将对象序列化为字节数组
         private static byte[] SerializableObjcet(Person<Work> p)
         {
 
             IFormatter formatter = new BinaryFormatter();
             MemoryStream stream = new MemoryStream();
             buffer = new byte[stream.Length];
             using (stream)
             {
                 formatter.Serialize(stream, p);
                 stream.Position = 0;
                 stream.Read(buffer, 0, buffer.Length);
             }
 
             Console.WriteLine("Serialization字节数组转换成功!");
             return buffer;
         }
         //将字节数组转化为对象
         private static void DeSerializableObject(byte[] bytes)
         {
 
             if (buffer != null)
             {
                 Person<Work> p;
                 IFormatter formatter = new BinaryFormatter();
                 MemoryStream stream = new MemoryStream(bytes);
                 using (stream)
                 {
                     p = (Person<Work>)formatter.Deserialize(stream);
                 }
                 Console.WriteLine(p.Name + "::" + p.Sex + "::" + p.Age);
                 Console.WriteLine("字节数组反序列化成功!");
             }
             else
             {
                 Console.WriteLine("字节数组为空!");
             }
         }
 
 执行结果如下:
 
 
 

原文地址:https://www.cnblogs.com/amylis_chen/p/2707338.html