zoukankan      html  css  js  c++  java
  • .NET序列化的一点技巧(附Demo)

    阅读目录

    介绍

      序列化是将对象状态转换为可保持或传输的形式的过程。序列化的补集是反序列化,后者将流转换为对象。这两个过程一起保证数据易于存储和传输。

    .NET Framework 提供了两个序列化技术:

    • 二进制序列化保持类型保真,这对于多次调用应用程序时保持对象状态非常有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等。远程处理使用序列化,“按值”在计算机或应用程序域之间传递对象。

    • XML 序列化只序列化公共属性和字段,并且不保持类型保真。当您希望提供或使用数据而不限制使用该数据的应用程序时,这一点非常有用。由于 XML 是开放式的标准,因此它对于通过 Web 共享数据来说是一个理想选择。SOAP 同样是开放式的标准,这使它也成为一个理想选择。

    详细

      具体命名空间:

      包含可用于序列化和反序列化对象的类。(包括System.Runtime.Serialization.Formatters.Binary.BinaryFormatter,还有WCF中用到的DataContractAttribute, DataMemberAttribute

      包含可用于将对象序列化为 XML 格式的文档或流的类。

      WCF大家很熟悉,一般的书籍都对基础的东西有很多内容的讲解,这里就对非WCF的一些序列化技巧抛个砖。

    一:序列化标记

      需要序列化:[Serializable]也可以写成[SerializableAttribute]

    特性“Serializable”只在“class, struct, enum, delegate”声明中有效。所以只能在类,结构体等上面标记。

      不需要序列化:[NonSerialized]也可以写成[NonSerializedAttribute]

    特性“NonSerialized”只在“field”声明中有效。所以只能在字段上标记,连属性器都不行。

    二:特殊情况:

      事件的标记:

    [field: NonSerializedAttribute()],需要加入field标记。

      属性的标记:

    其实我们叫的属性是属性器,是一对Get,Set方法。既然是方法,当然不是字段了,所以是不能序列化标记或者排除的,那我们怎么去处理某些属性不需要序列化的情况列。方法也是有的,需要把属性器中的Get,Set方法写实,即该有的字段还是得定义,不能偷懒,然后在该有的字段上面标记为不需要序列化。

    三:序列化的特殊用法

      学过C#的时候,大家都知道了个值类型,引用类型的概念,也可能知道了ICloneable这个接口,这个克隆接口可以复制对象,如实例化个student,然后调用Clone()即可以得到该对线的浅层副本

      浅层克隆就是只把改对象的值类型和引用类型的地址复制了,但是,原来对象中的被引用类型的对象发生改变,比如:student类中有个classroom,classroom中的某个字段发生改变,这样克隆后的对线的classroom的值也是会变的。除非classroom这个类也实现ICloneable接口。

      序列化克隆的好处就是不用考虑浅层复制,深层复制,直接将要克隆的对象序列化,然后反序列化得到的对象就是我们期望的结果。

    处理

      按照上面的说明,代码如下:

    Student类

     1     [Serializable]
     2     public class Student
     3     {
     4         [field: NonSerializedAttribute()]
     5         public event EventHandler Changed;
     6         [NonSerialized]
     7         private ExParam param;
     8 
     9         public string ID
    10         {
    11             get;
    12             set;
    13         }
    14 
    15         public string Name
    16         {
    17             get;
    18             set;
    19         }
    20 
    21         public ClassRoom Room
    22         {
    23             get;
    24             set;
    25         }
    26 
    27         public ExParam Param
    28         {
    29             get
    30             {
    31                 return param;
    32             }
    33             set
    34             {
    35                 param = value;
    36             }
    37         }
    38     }

    ClassRoom类

     1     [Serializable]
     2     public class ClassRoom
     3     {
     4 
     5         public string Name
     6         {
     7             get;
     8             set;
     9         }
    10 
    11         public string Address
    12         {
    13             get;
    14             set;
    15         }
    16     }

    ExParam类

    1     public class ExParam
    2     {
    3         public string Name
    4         {
    5             get;
    6             set;
    7         }
    8     }

    Util类

     1     public class Util
     2     {
     3         public static byte[] SerializeObject(object obj)
     4         {
     5             if (obj == null)
     6                 return null;
     7 
     8             using (MemoryStream memory = new MemoryStream())
     9             {
    10                 BinaryFormatter formatter = new BinaryFormatter();
    11                 formatter.Serialize(memory, obj);
    12                 memory.Position = 0;
    13                 byte[] read = new byte[memory.Length];
    14                 memory.Read(read, 0, read.Length);
    15                 memory.Close();
    16                 return read;
    17             }
    18         }
    19 
    20 
    21         public static object DeserializeObject(byte[] data)
    22         {
    23             object obj = null;
    24             if (data == null)
    25                 return obj;
    26 
    27             using (MemoryStream memory = new MemoryStream(data))
    28             {
    29                 memory.Position = 0;
    30                 BinaryFormatter formatter = new BinaryFormatter();
    31                 obj = formatter.Deserialize(memory);
    32                 memory.Close();
    33                 return obj;
    34             }
    35         }
    36     }

    主窗体

     1  private void Form1_Load(object sender, EventArgs e)
     2         {
     3             Student student = new Student()
     4             {
     5                 ID = "201401",
     6                 Name = "攻城狮",
     7                 Room = new ClassRoom()
     8                 {
     9                     Name = "博客园",
    10                     Address = "小山村"
    11                 },
    12                 Param = new ExParam()
    13                 {
    14                     Name = "程序猿"
    15                 }
    16             };
    17 
    18             byte[] data = Util.SerializeObject(student);
    19 
    20             Student student1 = Util.DeserializeObject(data) as Student;
    21 
    22             Print(student);
    23             Print(student1);
    24         }
    25 
    26         private void Print(Student student)
    27         {
    28             string info =string.Format("{0}{1}{2}{3}"
    29                          , "hashcode:" + student.GetHashCode().ToString() + " "
    30                          , student.ID + " " + student.Name + " "
    31                          , student.Room != null ? student.Room.Name + " " + student.Room.Address + " "+student.Room.GetHashCode().ToString()+" " : "room is null "
    32                          , student.Param != null ? student.Param.Name : "param is null"
    33                          );
    34             listPrint.Items.Add(info);
    35         }


    结论

      上述代码输出:

       

    从上述代码输出的结果我们可以看出

    • student是被序列化的,student1是用student的序列化的二进制反序列化出来的,两个的hashcode不一样,所以是两个对象。
    • 标记了序列化的字段都被序列化了,没标记的序列化字段Param是空的。
    • student中的属性Room是引用类型,标记为序列化,student和student1的Room里的值内容一样但是hashcode不一样,所以这Room也是我们期望的两个对象。

    Demo下载

    源码下载

  • 相关阅读:
    论文总结
    20179212 2017-2018-2 《密码与安全新技术》课程总结
    20179212 2017-2018-2 《密码与安全新技术》第6周作业
    SM234
    2017-2018-2 20179212 《网络攻防》 作业
    20179212 2017-2018-2 《密码与安全新技术》第5周作业
    第十周作业 缓冲区溢出攻防研究
    密码与安全新技术
    9th
    8th
  • 原文地址:https://www.cnblogs.com/mephisto/p/3702517.html
Copyright © 2011-2022 走看看