知识回看,说说连串化

C# 知识回顾 –  序列化

 【博主】反骨仔    【原文地址】

[C#] 说说序列化,

目录

  • 序列化的含义
  • 通过序列化保存对象数据
  • 众说纷纭

 

说说序列化

 【博主】反骨仔    【原文地址】

一、序列化的含义

  序列化
(Serialization)将对象的状态信息处理为字节流,以便于存储或传输到内存、数据库或文件的一个过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区,主要目的是保存对象的状态。便于日后从该状态中进行还原,创建新的对象,这个过程又称为反序列化。

 

1.1 序列化的工作方式

图片 1

图1.1-1

 

图片 2

  对象被序列化为字节流(包括数据、对象的类型信息:如版本、区域性和程序集名称)
–> 存储到 DB、IO 等地方。

 

目录

  • 序列化
  • 保存对象数据

 

1.2 用于序列化

  我们在数据交换的时候常进行序列化保存对象的数据信息,在需要使用它的时候再进行反序列化重新读取对象的信息并进行校验和存储的一些工作。常用于
Web 间传递数据,跨域传递,ASP .NET 后台代码往前端传递数据(js
进行解析处理)。

 

一、序列化

  序列化是将对象处理为字节流以存储对象或传输到内存、数据库或文件。其主要目的是保存对象的状态,以便可以在需要时重新创建对象。相反的过程称为反序列化。
 

1.3 使对象可序列化

  进行序列化的操作,需要:一个带序列化的对象,一个是包含序列化对象的流和一个序列化器(Formatter)。

  我们进行编写的类中,默认会给类加上 SerializableAttribute 特性的,当然你也可以使用显式的方式进行添加。当你打算对一个对象进行序列化时,如果它不包含 SerializableAttribute,将会引发异常。在某些时候,我们可能不希望类中的某些字段或属性进行序列化操作,你可以在该字段或属性上使用 NonSerializedAttribute ,以告诉序列化器不对它们进行序列化操作。

 

  【备注】如果已序列化的类中包含了其他类对象的引用,而这些类又恰巧也有
SerializableAttribute,那么它们也会被进行序列化。

  【备注】序列化的关键字特性:SerializableAttribute、NonSerializedAttribute。

 

  这里介绍一种常见的序列化和一种不常见的序列化:

  (1)二进制序列化:使用二进制编码来生成精简的序列化,会序列化所有成员,并提高性能。常用于存储和
socket 传输。

  (2)XML
序列化:可读性更高,也就表示有更高的灵活性,操作的便利性。可用 XmlSerializer 进行序列化操作。

 

 


1.1 序列化的工作方式

  此图显示序列化的整个过程。 图1.1-1

  图片 3
  对象被序列化为流。流传递的不仅是数据,还包括有关对象类型的信息,如对象的版本、区域性和程序集名称。通过该流,可以将对象存储在数据库、文件或内存中。

二、通过序列化保存对象数据

  这里使用
demo 进行简单演示如何对对象进行序列化和反序列化操作。

 

1.2 用于序列化

  通过序列化,开发人员可以保存对象的状态,并在需要时重新创建该对象,从而提供对象的存储以及数据交换。通过序列化,开发人员还可以执行类似如下的操作:通过
Web 服务将对象发送到远程应用程序、将对象从一个域传递到另一个域、以 XML
字符串的形式跨防火墙传递对象,或者跨应用程序维护安全信息或用户特定信息。

2.1 使用序列化保存对象

图片 4图片 5

 1     [Serializable]  //将类标记为可序列化
 2     public class Coupon : INotifyPropertyChanged
 3     {
 4         public decimal Amount { get; set; }
 5 
 6         public float InterestRate { get; set; }
 7 
 8         public int Term { get; set; }
 9 
10         private string _name;
11 
12         public string Name
13         {
14             get { return _name; }
15             set
16             {
17                 _name = value;
18                 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Customer"));
19             }
20         }
21 
22         [field: NonSerialized()]    //将可序列化的类中的某字段标记为不被序列化
23         public event PropertyChangedEventHandler PropertyChanged;
24 
25         public Coupon(decimal amount, float interestRate, int term, string name)
26         {
27             Amount = amount;
28             InterestRate = interestRate;
29             Term = term;
30             _name = name;
31         }
32     }

Coupon.cs

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             using (var stream = File.Create(fileName))
 7             {
 8                 var deserializer = new BinaryFormatter();  //二进制格式序列化器
 9                 deserializer.Serialize(stream, coupon);  //序列化对象到文件中
10             }
11         }

图片 6

图2-1 

 

  现在尝试反序列化,看看与之前 Coupon 对象的值是否一致。

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             //var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             //判断该文件是否存在
 7             if (!File.Exists(fileName))
 8             {
 9                 return;
10             }
11 
12             using (var stream = File.OpenRead(fileName))
13             {
14                 var deserializer = new BinaryFormatter();   //二进制序列化器
15                 var coupon = deserializer.Deserialize(stream) as Coupon;    //反序列化
16 
17                 if (coupon == null)
18                 {
19                     return;
20                 }
21 
22                 Console.WriteLine($"{nameof(Coupon)}:");
23                 Console.WriteLine($"    {nameof(coupon.Amount)}: {coupon.Amount}");
24                 Console.WriteLine($"    {nameof(coupon.InterestRate)}: {coupon.InterestRate}%");
25                 Console.WriteLine($"    {nameof(coupon.Term)}: {coupon.Term}");
26                 Console.WriteLine($"    {nameof(coupon.Name)}: {coupon.Name}");
27             }
28 
29             Console.Read();
30         }

图片 7

图2-2

 

1.3 使对象可序列化

  若要序列化对象,您需要待序列化的对象、要包含序列化对象的流,以及一个 Formatter。 System.Runtime.Serialization包含序列化和反序列化对象所需的类。
  将 SerializableAttribute 特性应用于一个类型可指示该类型的实例可以序列化。尝试序列化时,如果类型没有 SerializableAttribute 特性,将引发SerializationException 异常。
  如果不希望类中的字段可序列化,请应用 NonSerializedAttribute 特性。如果可序列化类型的字段包含指针、句柄或其他一些专用于特定环境的数据结构,并且不能在不同的环境中以有意义的方式重建,则可能需要使该字段不可序列化。
  如果已序列化的类包含对标记为 SerializableAttribute 的其他类的对象的引用,则也将序列化这些对象。

2.2 使用 SOAP 格式保存对象

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             using (var stream = File.Create(fileName))
 7             {
 8                 var deserializer = new SoapFormatter(); //Soap 格式化器
 9                 deserializer.Serialize(stream, coupon); //序列化
10             }
11         }

图片 8

图2-3

  反序列化时也采用 SoapFormatter 即可,结果同图2-2。

                var deserializer = new SoapFormatter();   //Soap 格式化器
                var coupon = deserializer.Deserialize(stream) as Coupon;    //反序列化

  【注意】不应将这些格式用于敏感数据,如密码或信用卡信息。

  【备注】二进制格式对于大多数
Windows 应用程序均适用。对于以前来说,使用
Web 应用程序或者是 Web 服务,建议使用 SOAP 的 XML
进行传输。而现在,当然是使用大众化的 json
格式进行传输啦。

 

  同样,也可以通过 XmlSerializer 将对象序列化保存在
XML 文件。我们可以根据需求选择合适的序列化器,操作基本是一样的。

 

1.3.1 二进制序列化和 XML 序列化

  可以使用二进制序列化或 XML
序列化。在二进制序列化中,会序列化所有成员(甚至包括那些只读成员),从而可以提高性能。XML
序列化提供了可读性更好的代码,并在对象共享和使用方面提供了更大的灵活性,以便实现互操作性。

众说纷纭

  @hi丶小时候 使用
SerializableAttribute
特性时,是不建议使用自动属性的,序列化后的字段都是多出
k_BackingField<> 17个字符,如果对象很大会浪费一部分流量,建议使用
DataContractAttribute 和 DataMemberAttribute

  @梁逸晨 除非对方系统强制要求 SOAP
才能通信,否则该人人抵制这么反人类的东西,建议楼主 JSON 或 Protobuf

 

 


【参考】

【参考】微软官方文档

 

1.3.2 二进制序列化

  二进制序列化使用二进制编码来生成精简的序列化,以用于存储或基于套接字的网络流等。

1.3.3 XML 序列化

  XML
序列化将对象的公共字段和属性或者方法的参数及返回值序列化为符合特定 XML
架构定义语言 (XSD) 文档的 XML 流。XML 序列化会生成具有转换为 XML
的公共属性和字段的强类型类。 System.Xml.Serialization 包含序列化和反序列化
XML 所需的类。
  您可以将特性应用于类和类成员,以控制 XmlSerializer 序列化或反序列化类实例的方式。

1.3.4 SOAP 序列化

  XML 序列化还可用于将对象序列化为符合 SOAP 规范的 XML 流。SOAP
是一种基于 XML 的协议,它是专门为使用 XML
来传输过程调用而设计的。如同常规的 XML 序列化,特性可用于控制 XML Web
services 生成的文本样式的 SOAP 消息。

1.3.5 基本序列化和自定义序列化

  可以通过两种方式执行序列化:基本序列化和自定义序列化。基本序列化使用
.NET Framework 来自动序列化对象。

1.3.5.1 基本序列化

  基本序列化的唯一要求是对象必须应用 SerializableAttribute 特性。 NonSerializedAttribute 可用于禁止序列化特定字段。

  使用基本序列化时,对象的版本控制可能会产生问题,在这种情况下,自定义序列化可能更合适。基本序列化是执行序列化的最简单的方法,但对进程提供的控制并不多。

1.3.5.2 自定义序列化

  在自定义序列化中,可以准确地指定将序列化哪些对象以及如何完成序列化。类必须标记为 SerializableAttribute,并实现 ISerializable 接口。
  如果希望同样以自定义方式反序列化对象,则必须使用自定义构造函数。

1.3.6 设计器序列化

  设计器序列化是一种特殊形式的序列化,它涉及通常与开发工具关联的对象持久性的种类。设计器序列化是将对象图转换为以后可用于恢复对象图的源文件的过程。源文件可以包含代码、标记,甚至包含
SQL 表信息。有关更多信息,请参见Designer Serialization Overview。  


二、保存对象数据

  虽然您可以在设计时将对象的属性设置为默认值,但是,如果该对象被损环,则在运行时输入的所有值均会丢失。 可以使用序列化在实例之间保持对象数据,从而能够存储值并且在下次实例化对象时检索这些值。
  在本演练中,将创建一个简单的对象,并将该对象的数据保存到文件中。然后,当您重新创建对象时将从该文件检索数据。最后,将修改代码以使用
SOAP 格式保持对象。  

2.1 使用序列化保存对象

图片 9 1
[Serializable] //将类标记为可序列化 2 public class Coupon :
INotifyPropertyChanged 3 { 4 public decimal Amount { get; set; } 5 6
public float InterestRate { get; set; } 7 8 public int Term { get; set;
} 9 10 private string _name; 11 12 public string Name 13 { 14 get {
return _name; } 15 set 16 { 17 _name = value; 18
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(“Customer”));
19 } 20 } 21 22 [field: NonSerialized()]
//将可序列化的类中的某字段标记为不被序列化 23 public event
PropertyChangedEventHandler PropertyChanged; 24 25 public Coupon(decimal
amount, float interestRate, int term, string name) 26 { 27 Amount =
amount; 28 InterestRate = interestRate; 29 Term = term; 30 _name =
name; 31 } 32 } Coupon.cs

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             using (var stream = File.Create(fileName))
 7             {
 8                 var deserializer = new BinaryFormatter();  //二进制格式序列化器
 9                 deserializer.Serialize(stream, coupon);  //序列化对象到文件中
10             }
11         }

图2-1 

 

  现在尝试反序列化,看看与之前 Coupon 对象的值是否一致。

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             //var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             //判断该文件是否存在
 7             if (!File.Exists(fileName))
 8             {
 9                 return;
10             }
11 
12             using (var stream = File.OpenRead(fileName))
13             {
14                 var deserializer = new BinaryFormatter();   //二进制序列化器
15                 var coupon = deserializer.Deserialize(stream) as Coupon;    //反序列化
16 
17                 if (coupon == null)
18                 {
19                     return;
20                 }
21 
22                 Console.WriteLine($"{nameof(Coupon)}:");
23                 Console.WriteLine($"    {nameof(coupon.Amount)}: {coupon.Amount}");
24                 Console.WriteLine($"    {nameof(coupon.InterestRate)}: {coupon.InterestRate}%");
25                 Console.WriteLine($"    {nameof(coupon.Term)}: {coupon.Term}");
26                 Console.WriteLine($"    {nameof(coupon.Name)}: {coupon.Name}");
27             }
28 
29             Console.Read();
30         }

图2-2

2.2 使用 SOAP 格式保存对象

 1         static void Main(string[] args)
 2         {
 3             const string fileName = @"demo1.txt";
 4             var coupon = new Coupon(10000, 0.2f, 1, "反骨仔");
 5 
 6             using (var stream = File.Create(fileName))
 7             {
 8                 var deserializer = new SoapFormatter(); //Soap 格式化器
 9                 deserializer.Serialize(stream, coupon); //序列化
10             }
11         }

图2-3

  反序列化时也采用 SoapFormatter 即可,结果同图2-2。

                var deserializer = new SoapFormatter();   //Soap 格式化器
                var coupon = deserializer.Deserialize(stream) as Coupon;    //反序列化

  【注意】本示例将数据存储到二进制或
SOAP 格式的文件中。不应将这些格式用于敏感数据,如密码或信用卡信息。

  【备注】二进制格式对于大多数
Windows 应用程序均适用。但对于
Web 应用程序或 Web 服务,您可能希望使用 SOAP 格式将对象保存到 XML
文件中,以使对象易于共享。

  也可以通过 XmlSerializer 将对象序列化保存在
XML 文件。根据需求选择合适的序列化器,操作基本是一样的。

 

 

—预览版,待整理完毕放到首页—

] 说说序列化, 说说序列化 【博主】反骨仔
【原文地址】 序 目录
序列化 保存对象数据 一、序列化…

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注