理论知识:

序列化是指将对象转换成字节流,从而存储对象或将对象传输到内存、数据库或文件的过程。 它的主要用途是保存对象的状态,以便能够在需要时重新创建对象。 反向过程称为“反序列化”。

序列化的工作原理

下图展示了序列化的整个过程:

将对象序列化为带有数据的流。 该流还可能包含有关对象类型的信息,例如其版本、区域性和程序集名称。 可以将此流中的对象存储在数据库、文件或内存中。

序列化的用途

通过序列化,开发人员可以保存对象的状态,并能在需要时重新创建对象,同时还能存储对象和交换数据。 通过序列化,开发人员可以执行如下操作:

  • 使用 Web 服务将对象发送到远程应用程序
  • 将对象从一个域传递到另一个域
  • 将对象通过防火墙传递为 JSON 或 XML 字符串
  • 跨应用程序维护安全或用户特定的信息

JSON 序列化

System.Text.Json 命名空间包含用于 JavaScript 对象表示法 (JSON) 序列化和反序列化的类。 JSON 是一种常用于在 Web 上共享数据的开放标准。

JSON 序列化将对象的公共属性序列化为符合 RFC 8259 JSON 规范的字符串、字节数组或流。 若要控制 JsonSerializer 对类的实例进行序列化或反序列化的方法,请执行以下操作:

二进制和 XML 序列化

System.Runtime.Serialization 命名空间包含用于对二进制和 XML 进行序列化和反序列化的类。

二进制序列化使用二进制编码来生成精简的序列化以供使用,如基于存储或套接字的网络流。 在二进制序列化中,所有成员(包括只读成员)都会被序列化,且性能也会有所提升。

XML 序列化将对象的公共字段和属性或方法的参数和返回值序列化成符合特定 XML 架构定义语言 (XSD) 文档要求的 XML 流。 XML 序列化生成已转换成 XML 的强类型类,其中包含公共属性和字段。 System.Xml.Serialization 包含用于对 XML 进行序列化和反序列化的类。 将特性应用于类和类成员,从而控制 XmlSerializer 如何序列化或反序列化类的实例。

让对象可序列化

若要对二进制或 XML 进行序列化,你需要:

将 SerializableAttribute 特性应用于某个类型,以指示可对此类型进行序列化的实例。 如果尝试对没有 SerializableAttribute 特性的类型进行序列化,则会引发异常。

若要防止对字段进行序列化,请应用 NonSerializedAttribute 特性。 如果可序列化的类型中的一个字段包含指针、句柄或特定环境专用的其他一些数据结构,且不能在其他环境中有意义地重构,不妨让其不可序列化。

如果已序列化的类引用被标记为 SerializableAttribute 的其他类的对象,那么这些对象也会被序列化。

基本和自定义序列化

可以使用两种方法对二进制和 XML 进行序列化:基本和自定义。

基本序列化使用 .NET Framework 自动序列化对象。 唯一的要求是类应用 SerializableAttribute 特性。 NonSerializedAttribute 可用于防止特定字段被序列化。

使用基本序列化时,对象的版本控制可能会产生问题。 对于重要的版本控制问题,可以使用自定义序列化。 基本序列化是最简单的序列化执行方式,但无法提供太多的进程控制。

在自定义序列化中,可以精确指定要序列化的对象以及具体执行方式。 类必须被标记为 SerializableAttribute,并实现 ISerializable 接口。 如果还希望按自定义方式反序列化对象,请使用自定义构造函数。

设计器序列化

设计器序列化是一种特殊形式的序列化,涉及与开发工具相关联的对象暂留。 设计器序列化是指将对象图转换成源文件以供日后用于恢复对象图的过程。 源文件可以包含代码、标记或 SQL 表信息。

演示代码

数据准备

    [Serializable]  //必须添加序列化特性
public class Person
{
[NonSerialized]
public int Id = 1; public string Name { get; set; } public string Sex { get; set; }
} [Serializable]  //必须添加序列化特性
public class Programmer : Person
{
private string Language { get; set; }//编程语言
public string Description { get; set; }
} public class DataFactory
{
/// <summary>
/// 初始化数据的
/// </summary>
/// <returns></returns>
public static List<Programmer> BuildProgrammerList()
{
#region data prepare
List<Programmer> list = new List<Programmer>();
list.Add(new Programmer()
{
Id = 1,
Description="高级班学员",
Name = "SoWhat",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "day",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "领悟",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "Sam",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "AlphaGo",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "折腾",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "Me860",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "打兔子的猎人",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "Nine",
Sex = "女"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "望",
Sex = "女"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "微笑刺客",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "waltz",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "爱在昨天",
Sex = "男"
});
list.Add(new Programmer()
{
Id = 1,
Description = "高级班学员",
Name = "waltz",
Sex = "男"
});
#endregion return list;
}
}
二进制序列化器
可以对单个对象或集合对象(如List<T>、ObservableCollection<T>)进行序列化。需要指出的是,需要对被序列化的对象添加[Serializable]特性
  /// <summary>
/// 二进制序列化器
/// </summary>
public static void BinarySerialize()
{
//使用二进制序列化对象
string fileName = Path.Combine(Constant.SerializeDataPath, @"BinarySerialize.txt");//文件名称与路径
using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{//需要一个stream,这里是直接写入文件了
List<Programmer> pList = DataFactory.BuildProgrammerList();
BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器
binFormat.Serialize(fStream, pList);
}
using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
{//需要一个stream,这里是来源于文件
BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器
//使用二进制反序列化对象
fStream.Position = 0;//重置流位置
List<Programmer> pList = (List<Programmer>)binFormat.Deserialize(fStream);//反序列化对象
}
}

soap序列化器

可以对单个对象进行序列化。但是,很大的缺陷在于,不能直接对泛型集合数据(如List<T>、ObservableCollection<T>)进行序列化(注:无论是根对象就是泛型集合,还是某个对象下的字段或属性是泛型集合,都不能序列化),
而要使用BinaryFormatter或XmlSerializer进行序列化。由于无法对泛型集合对象进行序列化,因此使用面比较窄,个人不建议使用SoapFormatter
 /// <summary>
/// soap序列化器
/// </summary>
public static void SoapSerialize()
{
//使用Soap序列化对象
string fileName = Path.Combine(Constant.SerializeDataPath, @"SoapSerialize.txt");//文件名称与路径
using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{
List<Programmer> pList = DataFactory.BuildProgrammerList();
SoapFormatter soapFormat = new SoapFormatter();//创建二进制序列化器
//soapFormat.Serialize(fStream, list);//SOAP不能序列化泛型对象
soapFormat.Serialize(fStream, pList.ToArray());
}
using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
{
SoapFormatter soapFormat = new SoapFormatter();//创建二进制序列化器
//使用二进制反序列化对象
fStream.Position = 0;//重置流位置
List<Programmer> pList = ((Programmer[])soapFormat.Deserialize(fStream)).ToList();//反序列化对象
}
}
 XML序列化器
无论对于单个对象还是集合对象(如List<T>、ObservableCollection<T>),都可以使用XmlSerializer进行序列化。需要指出的是,不需要对被序列化的对象添加[Serializable]特性注解。但是,使用XmlSeriabizable
的时候,被序列化的对象应该具有无参数构造函数。
 /// <summary>
/// XML序列化器
/// </summary>
public static void XmlSerialize()
{
//使用XML序列化对象
string fileName = Path.Combine(Constant.SerializeDataPath, @"Student.xml");//文件名称与路径
using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{
List<Programmer> pList = DataFactory.BuildProgrammerList();
XmlSerializer xmlFormat = new XmlSerializer(typeof(List<Programmer>));//创建XML序列化器,需要指定对象的类型
xmlFormat.Serialize(fStream, pList);
}
using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
{
XmlSerializer xmlFormat = new XmlSerializer(typeof(List<Programmer>));//创建XML序列化器,需要指定对象的类型
//使用XML反序列化对象
fStream.Position = 0;//重置流位置
List<Programmer> pList = pList = (List<Programmer>)xmlFormat.Deserialize(fStream);
}
}

Json序列化

目前业界,普通都采用此方式,优点很多,大家百度吧

    public class JsonHelper
{
#region Json
/// <summary>
/// JavaScriptSerializer
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string ObjectToString<T>(T obj)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
return jss.Serialize(obj);
} /// <summary>
/// JavaScriptSerializer
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="content"></param>
/// <returns></returns>
public static T StringToObject<T>(string content)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
return jss.Deserialize<T>(content);
} /// <summary>
/// JsonConvert.SerializeObject
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToJson<T>(T obj)
{
return JsonConvert.SerializeObject(obj);
} /// <summary>
/// JsonConvert.DeserializeObject
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="content"></param>
/// <returns></returns>
public static T ToObject<T>(string content)
{
return JsonConvert.DeserializeObject<T>(content);
}
#endregion Json
}

补充说明

****非常重要****。需要说明的是,反序列化的过程(从文件-->对象的过程),不是new出来新对象,然后对其进行赋值的。反序列化的时候,不是依据类代码对各个成员进行初步赋值,然后执行构造函数的过程。在反序列化的时候,既不会为成员初赋值,也不会执行构造函数,而是直接对没有标注为[NonSerialized]的字段赋给其保存在文件中的值,而对于标注为[NonSerialized]的字段,其结果仅仅是default(FiledType),此处的FieldType是指字段的类型(注:可以利用OnSerialized方法来事后修改字段的值)。例如:

[Serializable]

public class MyClass

{

public MyClass()

{

//在反序列化的时候,不会执行构造函数

}

private int x=10;   //在反序列化的时候,不是将10赋值给x。而是从数据文件中读取相应的值,直接赋值给x。

[NonSerializable]

private int y=15;   //在反序列化的时候,不会将15赋值给y。由于y标注了[NonSerializable],因此,反序列化完成的时候,y的值是default(int),也就是0。

private List<string> Strs=new List<string>();  //在反序列化的时候,不会new一个将List<string>并且赋值给Strs。而是从数据文件中读取相应的值,直接赋值给Strs。

[NonSerializable]

private List<string> AnotherStrs=new List<string>();  //在反序列化的时候,不会new一个List<string>并且将其赋值给AnotherStrs。由于AnotherStrs标注了[NonSerializable],因此,反序列化完成的时候,AnotherStrs的值是default(List<string>),也就是null。

}

参考资料:、

http://www.cppcns.com/ruanjian/csharp/115791.html
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/serialization/
https://blog.csdn.net/jiuzaizuotian2014/article/details/80974583
朝夕教育eleven老师演示代码

  

C# 序列化器的更多相关文章

  1. 在Wcf中应用ProtoBuf替代默认的序列化器

    Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...

  2. NetworkComms V3 使用Json序列化器进行网络通信

    刚才在网上闲逛,偶然看到一篇文章 C#(服务器)与Java(客户端)通过Socket传递对象 网址是:http://www.cnblogs.com/iyangyuan/archive/2012/12/ ...

  3. Android 使用xml序列化器生成xml文件

    在<Android 生成xml文件>一文中使用流的形式写入xml格式文件,但是存在一定的问题,那就是在短信内容中不能出现<>之类的括号,本文使用xml序列化器来解决 xml序列 ...

  4. 使用XML序列化器生成XML文件和利用pull解析XML文件

    首先,指定XML格式,我指定的XML格式如下: <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <message&g ...

  5. 使用XMl序列化器生成xml文件

    生成XML文件 创建几个虚拟的短信对象,存在list中 备份数据通常都是备份至sd卡 使用StringBuffer拼接字符串 把整个xml文件所有节点append到sb对象里 sb.append(&q ...

  6. ASP.NET MVC4 json序列化器

    ASP.NET MVC4中调用WEB API的四个方法 2012年06月07日00:05 it168网站原创 作者:廖煜嵘 编辑:景保玉 我要评论(0) [IT168技术]当今的软件开发中,设计软件的 ...

  7. WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)

    原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济 ...

  8. 使用紧凑的序列化器,数倍提升性能 —— ESFramework 4.0 快速上手(11)

    在分布式通信系统中,网络传递的是二进制流,而内存中是我们基于对象模型构建的各种各样的对象,当我们需要将一个对象通过网络传递给另一个节点时,首先需要将其序列化为字节流,然后通过网络发送给目标节点,目标节 ...

  9. xml生成方式二(Xml序列化器XmlSerializer)

    一.andoirdAPI提供了xml生成和解析的API: XmlSerializer xs = Xml.newSerializer();和XmlPullParser xmlPullParser = X ...

  10. DRF 序列化器-Serializer (2)

    作用 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器 ...

随机推荐

  1. [ABC233G] Strongest Takahashi

    Problem Statement There is a $N \times N$ grid, with blocks on some squares. The grid is described b ...

  2. [ABC235G] Gardens

    Problem Statement Takahashi has $A$ apple seedlings, $B$ banana seedlings, and $C$ cherry seedlings. ...

  3. 【软件安装】vmware虚拟机安装完整教程(15.5版本)

     目录 一.基础介绍 二.准备工作(注意:如果自己下载不下来翻到最下面获取下载地址) 三.VMware下载与安装 VMware Workstation15.5新功能 注意: 一.基础介绍 VMware ...

  4. Chrome扩展的核心:manifest 文件(中)

    大家好,我是 dom 哥.我正在写关于 Chrome 扩展开发的系列文章,感兴趣的可以 点个小星星 . 在上一篇中已经完成了 Chrome 扩展的雏形,本篇接着介绍 manifest 中的可选字段,完 ...

  5. 文心一言 VS 讯飞星火 VS chatgpt (169)-- 算法导论13.2 2题

    二.用go语言,证明:在任何一棵有 n 个结点的二叉搜索树中,恰有 n-1种可能的旋转. 文心一言: 要证明在任何一棵有 n 个结点的二叉搜索树中,恰有 n-1 种可能的旋转,我们可以按照以下步骤逐步 ...

  6. 关于开放签CA数字证书设计的思考

    这几天在调研CA数字证书以及思考如何在产品中集成使用CA数字证书,主要的目的和方向有以下几点: 有法律效力的电子文件的签署需要使用权威的证书颁发机构(CA)颁发的数字证书: 我们希望找到更便宜的证书方 ...

  7. k8s集群Node节点管理:节点信息查看及节点label标签管理

    k8s集群Node节点管理:节点信息查看及节点label标签管理 Kubernetes集群Node管理 一.查看集群信息 [root@k8s-master1 ~]# kubectl cluster-i ...

  8. java算法易筋经:常见java-API使用技巧

    摘要:算法练习的本质也在于锻炼编程思维,强化程序员的内力.因此给自己后面会持续更新的算法技巧内容简称算法易筋经. 本文分享自华为云社区<<java算法易筋经>之常见java-API使 ...

  9. 带你聚焦GaussDB(DWS)存储时游标使用

    摘要:游标是一种数据处理方法,提供了在查询结果集中进行逐行遍历浏览数据的方法,也可以将游标当做上下文区域的句柄或者指针,借助游标对指定位置的数据进行查询与处理. 本文分享自华为云社区<Gauss ...

  10. JVM内存模型,你看这一篇就够了

    摘要:JVM是一种用于计算设备的规范,是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的. 本文分享自华为云社区<[云驻共创]JVM内存模型的探知之旅>,作者:多米 ...