当前位置: 首页 > news >正文

C# 序列化技术全面解析:原理、实现与应用场景

在软件开发中,数据持久化和网络通信是两个至关重要的环节。想象一下,当我们需要将一个复杂的对象保存到文件中,或者通过网络发送到另一台计算机时,如何有效地表示这个对象?这就是序列化技术要解决的问题。序列化(Serialization)是将对象转换为可存储或传输的格式的过程,而反序列化(Deserialization)则是将这些数据重新转换为对象的过程。

C# 作为一门成熟的面向对象编程语言,提供了丰富多样的序列化解决方案。本文将全面探讨 C# 中的各种序列化技术,包括二进制序列化、XML 序列化、JSON 序列化以及数据契约序列化,分析它们的原理、实现方式、优缺点以及适用场景,并通过实际代码示例展示如何在项目中应用这些技术。

一、序列化基础概念

1.1 什么是序列化

序列化是指将对象的状态信息转换为可以存储或传输的形式的过程。在序列化过程中,对象将其当前状态(通常是其成员变量的值)写入到临时或持久性存储区。之后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

1.2 为什么需要序列化

序列化技术主要解决以下几个问题:

  1. 数据持久化:将对象状态保存到文件或数据库中,以便后续重新加载

  2. 远程通信:在不同应用程序域或网络中的计算机之间传输对象

  3. 进程间通信:在不同进程之间传递复杂数据结构

  4. 缓存机制:将对象缓存到内存或分布式缓存中

1.3 C# 中的序列化分类

C# 提供了多种序列化方式,主要可以分为以下几类:

  1. 二进制序列化

  2. XML 序列化

  3. JSON 序列化

  4. 数据契约序列化

  5. 自定义序列化

每种方式都有其特点和适用场景,开发者需要根据具体需求选择合适的序列化方式。

二、二进制序列化

2.1 二进制序列化概述

二进制序列化是将对象转换为二进制格式的过程,这种格式通常非常紧凑且处理速度快。在 .NET Framework 中,可以使用 BinaryFormatter 类来实现二进制序列化。

2.2 实现二进制序列化

下面是一个完整的二进制序列化示例:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;[Serializable]
public class Person
{public string Name { get; set; }public int Age { get; set; }[NonSerialized]public string TemporaryData; // 这个字段不会被序列化
}public class BinarySerializationDemo
{public static void Demo(){Person person = new Person { Name = "张三", Age = 30, TemporaryData = "临时数据" };// 序列化byte[] serializedData;using (MemoryStream stream = new MemoryStream()){BinaryFormatter formatter = new BinaryFormatter();formatter.Serialize(stream, person);serializedData = stream.ToArray();}Console.WriteLine($"序列化后的字节数: {serializedData.Length}");// 反序列化using (MemoryStream stream = new MemoryStream(serializedData)){BinaryFormatter formatter = new BinaryFormatter();Person deserializedPerson = (Person)formatter.Deserialize(stream);Console.WriteLine($"姓名: {deserializedPerson.Name}");Console.WriteLine($"年龄: {deserializedPerson.Age}");Console.WriteLine($"临时数据: {deserializedPerson.TemporaryData ?? "null"}");}}
}

2.3 二进制序列化的特点

优点:

  1. 序列化后的数据非常紧凑,占用空间小

  2. 序列化和反序列化速度快

  3. 可以完整保留对象图和类型信息

缺点:

  1. 数据不可读,难以调试

  2. 平台依赖性较强

  3. 在 .NET Core/.NET 5+ 中被认为不安全,已不建议使用

2.4 安全注意事项

由于 BinaryFormatter 存在严重的安全风险,微软已从 .NET Core 开始不推荐使用它。攻击者可能利用它执行任意代码。如果确实需要使用二进制序列化,可以考虑以下替代方案:

  1. 使用 System.Text.Json 或 Newtonsoft.Json 进行 JSON 序列化

  2. 使用 XmlSerializer 进行 XML 序列化

  3. 实现自定义的二进制序列化

三、XML 序列化

3.1 XML 序列化概述

XML 序列化将对象的公共属性和字段转换为 XML 格式。与二进制序列化不同,XML 序列化不包含类型信息,只序列化公共属性和字段。

3.2 实现 XML 序列化

using System;
using System.IO;
using System.Xml.Serialization;[Serializable]
public class Product
{public int Id { get; set; }public string Name { get; set; }public decimal Price { get; set; }[XmlIgnore]public DateTime CreatedAt { get; set; } // 这个属性不会被序列化
}public class XmlSerializationDemo
{public static void Demo(){Product product = new Product { Id = 1001, Name = "笔记本电脑", Price = 5999.99m,CreatedAt = DateTime.Now};// 序列化XmlSerializer serializer = new XmlSerializer(typeof(Product));string xmlString;using (StringWriter writer = new StringWriter()){serializer.Serialize(writer, product);xmlString = writer.ToString();}Console.WriteLine("序列化的XML:");Console.WriteLine(xmlString);// 反序列化using (StringReader reader = new StringReader(xmlString)){Product deserializedProduct = (Product)serializer.Deserialize(reader);Console.WriteLine($"\n反序列化结果:");Console.WriteLine($"ID: {deserializedProduct.Id}");Console.WriteLine($"名称: {deserializedProduct.Name}");Console.WriteLine($"价格: {deserializedProduct.Price}");Console.WriteLine($"创建时间: {deserializedProduct.CreatedAt}");}}
}

3.3 XML 序列化的特点

优点:

  1. 生成的 XML 可读性强

  2. 跨平台兼容性好

  3. 可以通过 XSD 验证数据格式

  4. 支持通过属性精细控制序列化过程

缺点:

  1. 数据冗余多,文件体积较大

  2. 序列化和反序列化性能较低

  3. 只能序列化公共成员

3.4 XML 序列化高级控制

通过使用各种 XML 特性,可以精细控制序列化过程:

[XmlRoot("ProductItem")]
public class AdvancedProduct
{[XmlAttribute("productId")]public int Id { get; set; }[XmlElement("productName")]public string Name { get; set; }[XmlElement("productPrice")]public decimal Price { get; set; }[XmlElement("isAvailable")]public bool IsAvailable { get; set; }[XmlArray("Categories")][XmlArrayItem("Category")]public List<string> Categories { get; set; }
}

四、JSON 序列化

4.1 JSON 序列化概述

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成。在 Web 开发和 API 设计中,JSON 已成为事实上的标准。

C# 中有两种主要的 JSON 序列化实现:

  1. System.Text.Json (.NET Core 3.0 及以后版本内置)

  2. Newtonsoft.Json (流行的第三方库)

4.2 使用 System.Text.Json 实现 JSON 序列化

using System;
using System.Text.Json;
using System.Text.Json.Serialization;public class Order
{public int OrderId { get; set; }public string CustomerName { get; set; }[JsonPropertyName("items")]public List<OrderItem> OrderItems { get; set; }[JsonIgnore]public string InternalNote { get; set; }
}public class OrderItem
{public string ProductName { get; set; }public int Quantity { get; set; }public decimal UnitPrice { get; set; }
}public class SystemTextJsonDemo
{public static void Demo(){Order order = new Order{OrderId = 1001,CustomerName = "李四",InternalNote = "重要客户",OrderItems = new List<OrderItem>{new OrderItem { ProductName = "鼠标", Quantity = 2, UnitPrice = 89.50m },new OrderItem { ProductName = "键盘", Quantity = 1, UnitPrice = 199.00m }}};// 序列化选项var options = new JsonSerializerOptions{WriteIndented = true, // 美化输出PropertyNamingPolicy = JsonNamingPolicy.CamelCase // 驼峰命名};// 序列化string jsonString = JsonSerializer.Serialize(order, options);Console.WriteLine("序列化的JSON:");Console.WriteLine(jsonString);// 反序列化Order deserializedOrder = JsonSerializer.Deserialize<Order>(jsonString, options);Console.WriteLine($"\n反序列化结果 - 订单ID: {deserializedOrder.OrderId}");Console.WriteLine($"客户名称: {deserializedOrder.CustomerName}");Console.WriteLine($"订单项数: {deserializedOrder.OrderItems?.Count ?? 0}");}
}

4.3 使用 Newtonsoft.Json 实现 JSON 序列化

using System;
using Newtonsoft.Json;public class NewtonsoftJsonDemo
{public static void Demo(){var data = new{Name = "王五",Age = 35,IsActive = true,LastLogin = DateTime.Now,Scores = new[] { 90, 85, 95 }};// 序列化设置var settings = new JsonSerializerSettings{Formatting = Formatting.Indented,NullValueHandling = NullValueHandling.Ignore,DateFormatString = "yyyy-MM-dd HH:mm:ss"};// 序列化string json = JsonConvert.SerializeObject(data, settings);Console.WriteLine("使用Newtonsoft.Json序列化的JSON:");Console.WriteLine(json);// 反序列化var deserializedData = JsonConvert.DeserializeAnonymousType(json, data, settings);Console.WriteLine($"\n反序列化结果 - 姓名: {deserializedData.Name}");Console.WriteLine($"年龄: {deserializedData.Age}");}
}

4.4 JSON 序列化的特点

优点:

  1. 数据格式轻量,文件体积小

  2. 可读性较好

  3. 广泛支持于各种编程语言和平台

  4. 在 Web 开发中已成为标准

缺点:

  1. 相比二进制格式,仍然有一定冗余

  2. 处理某些复杂类型(如循环引用)需要额外配置

4.5 System.Text.Json vs Newtonsoft.Json

特性System.Text.JsonNewtonsoft.Json
性能更高较低
内存分配更少较多
功能丰富度基本功能非常丰富
内置支持.NET Core 3.0+需要安装NuGet包
异步序列化支持不支持
处理循环引用有限支持完善支持

对于新项目,建议优先使用 System.Text.Json,除非需要 Newtonsoft.Json 的某些特有功能。

五、数据契约序列化

5.1 数据契约序列化概述

数据契约序列化是 WCF (Windows Communication Foundation) 中使用的一种序列化机制,通过 DataContractSerializer 类实现。它比 XML 序列化更灵活,但需要显式标记要序列化的成员。

5.2 实现数据契约序列化

using System;
using System.IO;
using System.Runtime.Serialization;[DataContract]
public class Employee
{[DataMember(Name = "id")]public int EmployeeId { get; set; }[DataMember]public string Name { get; set; }[DataMember(Order = 3)]public string Department { get; set; }public string SecretCode { get; set; } // 不会被序列化
}public class DataContractSerializationDemo
{public static void Demo(){Employee emp = new Employee{EmployeeId = 1001,Name = "赵六",Department = "研发部",SecretCode = "ABC123"};// 序列化DataContractSerializer serializer = new DataContractSerializer(typeof(Employee));string xmlString;using (var stream = new MemoryStream()){serializer.WriteObject(stream, emp);stream.Position = 0;using (var reader = new StreamReader(stream)){xmlString = reader.ReadToEnd();}}Console.WriteLine("数据契约序列化的XML:");Console.WriteLine(xmlString);// 反序列化using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlString))){Employee deserializedEmp = (Employee)serializer.ReadObject(stream);Console.WriteLine($"\n反序列化结果 - ID: {deserializedEmp.EmployeeId}");Console.WriteLine($"姓名: {deserializedEmp.Name}");Console.WriteLine($"部门: {deserializedEmp.Department}");Console.WriteLine($"密码: {deserializedEmp.SecretCode ?? "null"}");}}
}

5.3 数据契约序列化的特点

优点:

  1. 对序列化过程有更精细的控制

  2. 支持版本控制,对数据变更更友好

  3. 可以处理复杂对象图和继承层次结构

  4. 性能优于 XML 序列化

缺点:

  1. 需要显式标记要序列化的成员

  2. 生成的 XML 不如 XmlSerializer 生成的那么简洁

  3. 主要用于 WCF 服务

六、序列化技术选型指南

在选择序列化技术时,应考虑以下因素:

  1. 性能需求:二进制 > JSON ≈ 数据契约 > XML

  2. 数据大小:二进制 < JSON < 数据契约 < XML

  3. 可读性:XML ≈ JSON > 数据契约 > 二进制

  4. 跨平台支持:JSON > XML > 数据契约 > 二进制

  5. 类型安全:二进制 > 数据契约 > XML ≈ JSON

  6. 安全考虑:JSON ≈ XML > 数据契约 > 二进制

推荐场景:

  • Web API/前后端通信:JSON (System.Text.Json 或 Newtonsoft.Json)

  • 配置文件:JSON 或 XML

  • 高性能本地存储:考虑自定义二进制格式或 Protocol Buffers

  • WCF 服务:数据契约序列化

  • 临时对象存储:二进制序列化(仅限可信环境)

七、高级主题与最佳实践

7.1 处理循环引用

循环引用是指对象之间相互引用形成的环。默认情况下,许多序列化器无法处理这种情况。

在 Newtonsoft.Json 中处理循环引用:

var settings = new JsonSerializerSettings
{PreserveReferencesHandling = PreserveReferencesHandling.Objects,ReferenceLoopHandling = ReferenceLoopHandling.Serialize
};
string json = JsonConvert.SerializeObject(obj, settings);

在 System.Text.Json 中处理循环引用:

var options = new JsonSerializerOptions
{ReferenceHandler = ReferenceHandler.Preserve
};
string json = JsonSerializer.Serialize(obj, options);

 

7.2 自定义序列化

对于需要特殊处理的类型,可以实现自定义序列化逻辑:

public class CustomObject : IJsonOnSerializing, IJsonOnSerialized, IJsonOnDeserializing, IJsonOnDeserialized
{public string Data { get; set; }void IJsonOnSerializing.OnSerializing(){Console.WriteLine("序列化前调用");}void IJsonOnSerialized.OnSerialized(){Console.WriteLine("序列化后调用");}void IJsonOnDeserializing.OnDeserializing(){Console.WriteLine("反序列化前调用");}void IJsonOnDeserialized.OnDeserialized(){Console.WriteLine("反序列化后调用");}
}

7.3 版本兼容性考虑

在设计可序列化类型时,应考虑未来可能的变更:

  1. 避免删除已序列化的字段,可以标记为废弃

  2. 新添加的字段应提供合理的默认值

  3. 考虑使用 [OptionalField] 特性标记可能不存在的字段

  4. 实现 ISerializable 接口进行自定义版本控制

7.4 性能优化建议

  1. 对于频繁序列化的类型,缓存序列化器实例

  2. 对于大型对象,考虑流式序列化

  3. 使用 ArrayPool<byte> 减少内存分配

  4. 在 ASP.NET Core 中,使用 System.Text.Json 源生成器

八、结论

C# 提供了丰富多样的序列化技术,每种技术都有其适用场景。在现代应用开发中,JSON 序列化已成为最常用的方式,特别是对于 Web API 和前后端通信。System.Text.Json 作为 .NET 平台的新标准,提供了高性能和低内存占用的优势,而 Newtonsoft.Json 则因其丰富的功能仍然在许多项目中使用。

对于需要更高性能的场景,可以考虑二进制序列化,但应注意其安全风险。XML 序列化在需要严格模式验证或与旧系统集成的场景中仍然有价值。数据契约序列化则是 WCF 服务开发的首选。

选择序列化技术时,开发者应综合考虑性能需求、数据大小、可读性要求、跨平台需求和安全性等因素。理解各种序列化技术的原理和特点,能够帮助我们在实际项目中做出更合理的技术选型,构建更健壮、高效的应用程序。

 

http://www.xdnf.cn/news/753175.html

相关文章:

  • 基于大模型预测的寻常型天疱疮诊疗方案研究报告
  • ERP系统中商品定价功能设计:支持渠道、会员与批发场景的灵活定价机制
  • 行业分析---小米汽车2025第一季度财报
  • 基于Python学习《Head First设计模式》第二章 观察者模式
  • 基于 Flickr30k-Entities 数据集 的 Phrase Localization
  • 动态规划第二弹:路径类问题(不同路径,珠宝的最高价值,地下城游戏)
  • rtpmixsound:实现音频混音攻击!全参数详细教程!Kali Linux教程!
  • 五、单元测试-概述入门
  • SQL进阶之旅 Day 10:执行计划解读与优化
  • FFmpeg学习笔记
  • SDL_CreateRendererWithProperties报错Parameter ‘window‘ is invalid
  • Maven概述,搭建,使用
  • leetcode-hot-100 (矩阵)
  • 设计模式——组合设计模式(结构型)
  • Android第十一次面试补充篇
  • 读《Go语言圣经记录》(二):深入理解Go语言的程序结构
  • NodeJS全栈开发面试题讲解——P10微服务架构(Node.js + 多服务协作)
  • VMware Tools 手动编译安装版
  • qwen-0.5b小模型的用处和显存要求
  • Unity Mono与IL2CPP比较
  • 大模型备案中语料安全详细说明
  • 开源库免费API服务平台 ALLBEAPI
  • unix/linux source 命令,其内部结构机制
  • unix/linux source 命令,其高级使用
  • 通义开源视觉感知多模态 RAG 推理框架 VRAG-RL:开启多模态推理新时代
  • 【前端】html2pdf实现用前端下载pdf
  • Python Django完整教程与代码示例
  • Vue3 + Element Plus 防止按钮重复点击的解决方案
  • LabVIEW多按键自动化检测系统
  • 03 APP 自动化-定位元素工具元素定位