LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

一文教你掌握C#中的对象序列化:原理和实践

admin
2026年1月15日 14:12 本文热度 115

最近集成一个医院PACS接口时,里面字段太多了,我本来想自己写反射代码生成请求的XML,但后面想想,算了,直接用序列化吧。

这里就对C#中的序列化做个总结,日后再用到也有个参考。

 

正文

本文介绍了C#中的序列化及4种序列化对象的方法(BinaryFormatter、SoapFormatter、XmlSerializer、JsonSerializer)。

本文只做了入门级的总结 ,如果需深入了解这几种序列化的方法,可以访问MSDN上的文档。

说明:目前流行的序列化方案是Json和Protobuf。

其中Json可以使用内置的System.Text.Json库也可以使用Newtonsoft.Json库。

关于Protobuf的序列化,后面出一篇文章单独介绍

 

注意:自.NET 5起,已经不推荐使用BinaryFormatter和SoapFormatter了。

https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/binaryformatter-security-guide#binaryformatter-security-vulnerabilities

 

对象序列化

序列化是指持久化一个对象的状态到流(如文件流和内存流)的过程。被持久化的数据次序包括以后所有需要用来重建(即反序列化)对象状态所必需的信息。使用序列化,用最小花费来保存各种格式数据就变得轻而易举了。

 

对象图的作用

当一个对象被持久化到流时,所有的相关数据(基类、包含的对象等)也会被自动序列化,因此,假设我们想持久化一个子类,那么继承链接(即父类、子类的子类)上的所有数据都会被包括进来,也就是对象图。

对象图使用箭头来表示“需要”和“依赖”的关系。

 

举一个简单的例子,假设有以下的数据模型定义

public class Car    {        protected Radio Radio { get; set; }    }
    public class Radio    {
    }
    public class JamesBondCar : Car    {
    }

有一个基类Car,它配有(has a )Radio。JamsBondCar类扩展Car基类。下图显示了一个模拟这些关系可能的对象图

 Car类引用了Radio类(有has-a关系),JamesBondCar类引用了Car类(是is-a关系),也引用了Radio类(因为它继承了这个受保护的成员变量)

 

可以用下面简单的公式来描述

[Car3 , ref 2]    =》 对象3(Car类)依赖于对象2(Radio类)

[Radio 2]  =》 对象2(Radio类)不依赖其它

[JamesBondCar 1, ref 3, ref 2]  =》 对象1(JamesBondCar类)依赖于对象3和对象2。

因此在序列化或反序列化JamesBondCar类的实例时,对象图确认了Radio类型和Car类型也参与了这个过程。

 

定义可序列化的对象

使用[Serializable]特性可以标记为可序列化对象。

使用[NonSerialized]特性可以标记成员不会被序列化

public class Student    {        private int id;
        private string name;
        private string remark;
        public int Id { get => id; set => id = value; }        public string Name { get => name; set => name = value; }        public string Remark { get => remark; set => remark = value; }    }

值得注意的是,[Serializable]特性不会被继承,因此子类也需要标记为[Serializable]

对于XmlSerializer和JsonSerializer,可以不用[Serializable]标记也能正常执行。

对于BinaryFormatter或SoapFormatter序列化未使用[Serializable]标记的类时,会抛出SerializationException异常。

 

BinaryFormatter

BinaryFormatter在序列化对象时,会持久化每个类型的完全限定名称和定义程序集的完整名称。也叫类型保真(type fidelity)

这种方式有利也有弊。优点就是,使用BinaryFormatter序列化出来的文件可以移植到其它设备,并完整地恢复到对象的原始状态。缺点就是:因为这些类型都是.NET里面定义的,所以只能供.NET使用,其它编程语言无法使用。

 

使用BinaryFormatter进行序列化的方法如下:

这里以前面的Student类为例

public static void Main(){     Student student = new Student();     student.Id = 1;     student.Name = "Name";     student.Remark = "Remard";     SaveAsBinaryFile(student, "D:\\student.dat");}
static void SaveAsBinaryFile(object obj,string filePath){     BinaryFormatter binaryFormatter = new BinaryFormatter();     using(FileStream fs = new FileStream(filePath,FileMode.Create))     {           binaryFormatter.Serialize(fs, obj);     }
}

 序列化保存出来的文件,使用16进制编辑器打开如下

可见BinaryFormatter.Serialize()是一个负责生成对象图,并将字节顺序移动到流的方法。

这里的流可以是其它类型的流,如内存流,网络流等。示例中使用了文件流,直接保存到了文件。

 

使用BinaryFormatter进行反序列化的方法如下: 

static object BinaryFileToObject(string filePath)        {            BinaryFormatter binaryFormatter = new BinaryFormatter();            using(FileStream fs = new FileStream(filePath,FileMode.Open))            {                return binaryFormatter.Deserialize(fs);            }        }
1 var stu = (Student)BinaryFileToObject(file);2 Console.WriteLine(stu.Id);

SoapFormatter

SoapFormatter类型把对象持久化为一个SAOP消息。

SoapFormatter通过使用XML命名空间来持久化原始程序集的跟踪,它不是类型保真的。

 

SoapFormatter进行序列化的方法如下:

说明:需要引用 System.Runtime.Serialization.Formattters.Soap.dll

var file = "D:\\soap.soap";Student student = new Student();student.Id = 1;student.Name = "Name";student.Remark = "Remard";SaveAsSOAPFile(student, file);
static void SaveAsSOAPFile(object obj, string filePath)        {            SoapFormatter soapFormatter = new SoapFormatter();            using (FileStream fs = new FileStream(filePath, FileMode.Create))            {                soapFormatter.Serialize(fs, obj);            }        }

序列化出来的结果如下:

 

 SoapFormatter进行反序列化的方法如下:

static object SOAPFileToObject(string filePath){    SoapFormatter soapFormatter = new SoapFormatter();    using (FileStream fs = new FileStream(filePath, FileMode.Open))    {          return soapFormatter.Deserialize(fs);    }}
1  var stu = (Student)SOAPFileToObject(file);2  Console.WriteLine(stu.Id);

XmlSerializer

使用XmlSerializer可以将对象的所有公有字段/属性持久化为XML元素。

使用XmlSerializer进行序列化的方法如下:

static void Main(string[] args){    Student student = new Student();    student.Id = 1;    student.Name = "Name";    student.Remark = "Remark";    SaveAsXmlFile(student, "D:\\output.xml");}
static void SaveAsXmlFile(object obj,string filePath){    XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());    using(FileStream fs = new FileStream(filePath, FileMode.Create))    {          xmlSerializer.Serialize(fs, obj);    }}

序列化出来的结果如下:

 

 使用XmlSerializer进行反序列化的方法如下:

static T XmlFileToObject<T>(string filePath){     XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));     using (FileStream fs = new FileStream(filePath, FileMode.Open))     {            return (T)xmlSerializer.Deserialize(fs);     }}
Student stu = XmlFileToObject<Student>("D:\\output.xml");Console.WriteLine(stu.Name);

 

使用XmlSerializer序列化到字符串

public string XmlSerializeToString(object obj){      XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());      StringBuilder stringBuilder = new StringBuilder();                //不显示默认命名空间 xsi和xsd      var emptyNamespaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });      var settings = new XmlWriterSettings();      settings.Indent = true;                    //缩进      settings.OmitXmlDeclaration = true;        //移除XML声明      using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder,settings))      {          xmlSerializer.Serialize(xmlWriter, obj,emptyNamespaces);          return stringBuilder.ToString();      }}

在使用XmlSerializer进行序列化时,可以控制 XML数据的生成,这里放到下一遍文章中来进行讲解。

 

JsonSerializer

使用JsonSerializer可以将对象持久化成json字符串。这对于调用WebApi时非常有用。

System.Text.JsonSerializer并不是.Net Framework内置的库,而是伴随.NET Core 3.0一起发布的一套扩展库。

它支持

  • .NET Standard 2.0 and later
  • .NET Framework 4.6.2 and later
  • .NET Core 2.1 and later
  • .NET 5 and later

使用Nuget 搜索安装 System.Text.Json进行安装

 

使用JsonSerializer进行序列化的方法如下:

static void Main(string[] args){     Student student = new Student();     student.Id = 1;     student.Name = "Name";     student.Remark = "Remark";
     var json = ObjectConvertToJson(student);     Console.WriteLine(json);}
static string ObjectConvertToJson(object obj){     var json = JsonSerializer.Serialize(obj);     return json;}

运行结果如下:

 

使用JsonSerializer进行反序列化的方法如下:

static T JsonToObject<T>(string json){     return JsonSerializer.Deserialize<T>(json);}
var stu = JsonToObject<Student>(json);Console.WriteLine(stu.Name);

 

参考资料:

.NET序列化

https://learn.microsoft.com/en-us/dotnet/standard/serialization/

 

XML序列化

https://learn.microsoft.com/en-us/dotnet/standard/serialization/introducing-xml-serialization

 

Json序列化

https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/overview


该文章在 2026/1/16 10:07:03 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved