序列化 - Snet Docs

序列化与数据转换 (Serialization & Data Conversion)

最后更新: 2026-07-21 程序集: Snet.Utility / Snet.Core 命名空间: Snet.Utility, Snet.Core.extend


概述

Snet 框架提供了全面的序列化和转换工具集,涵盖 JSON、Protobuf、XML、字节操作、哈希、加密、编码、文件 I/O 和深拷贝。所有方法均为标准 .NET 类型的扩展方法,支持流畅的链式调用。


架构

Snet.Utility.ExtendMethod (静态类, 4000+ 行)
  |
  +-- System.Text.Json 序列化 (ToJson, ToJsonEntity, JsonFormatting)
  +-- Newtonsoft.Json 序列化 (ToNJson, ToNJsonEntity)
  +-- Protobuf 序列化 (ToProtobuf, ToProtobufEntity) [protobuf-net]
  +-- XML 序列化 (ToXml, ToXmlEntity) [XmlSerializer]
  +-- AES 加密 / 解密
  +-- SHA256 / SHA1 / MD5 哈希
  +-- Base64 编码 / 解码
  +-- 字节序 (ReverseBytes, ReverseEndianness, ToNetworkByteOrder)
  +-- 结构体封送 (ByteArrayToStructure, StructureToByteArray)
  +-- 深拷贝 (DeepCopy 通过 JSON 往返, CopyArray 通过 Array.Copy)
  +-- 验证 (IsJson, IsGuid, IsNumber, IsEmail 等)
  +-- 类型转换 (ToInt, ToLong, ToDecimal, ToDateTime 等)
  +-- 字符串工具 (UrlEncode, HtmlEncode, JoinList 等)

Snet.Utility.ByteHandler (静态类)
  +-- 100+ 字节转换方法
  +-- Hex/ASCII 转换, CRC 计算, 位操作
  +-- 字节拆分/分割, 数组扩展
  +-- 整数 <-> byte[] 转换

Snet.Utility.XmlHandler (实例类)
  +-- 完整 XML CRUD: XmlSerialize, XmlDeserialize
  +-- XmlDocument 操作: Read, Insert, Update, Delete
  +-- DataSet/Table 集成
  +-- XXE 安全防护 (XmlResolver=null)
  +-- 缓存的 XmlSerializer (ConcurrentDictionary)

Snet.Utility.FileHandler (静态类)
  +-- FileToString / StringToFile (+ 异步版本)
  +-- ConvertToBinary, GetFolderPath

Snet.Core.extend.CoreExtend (静态类)
  +-- WriteGetBytes (数值 -> byte[])
  +-- ReadGetLength (DataType -> 字节大小)
  +-- GetEncoding (EncodingType? -> System.Text.Encoding)
  +-- MessageStandard (消息格式标准化)

JSON 序列化 (System.Text.Json)

主要的 JSON 库。Snet.Utility.ExtendMethod 上的扩展方法。

序列化

// 基础: 对象 -> JSON 字符串
string json = obj.ToJson();              // 紧凑格式 (无缩进)
string json = obj.ToJson(formatting: true);  // 美化输出

// 使用自定义选项
var options = new JsonSerializerOptions { WriteIndented = true };
string json = obj.ToJson(options);

内部使用的默认选项:

  • IncludeFields = true -- 除了属性外还序列化字段
  • NumberHandling = AllowNamedFloatingPointLiterals -- 支持 NaN, Infinity
  • Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping -- 最小转义,ASCII 可读
  • WriteIndented = false (紧凑) / true (格式化)

反序列化

// 基础: JSON 字符串 -> 类型化对象
var entity = json.ToJsonEntity<MyType>();

// 使用自定义选项
var entity = json.ToJsonEntity<MyType>(new JsonSerializerOptions { ... });

美化输出

string formatted = compactJson.JsonFormatting();

JSON 序列化 (Newtonsoft.Json)

用于向后兼容的传统 JSON 库。

// 序列化
string json = obj.ToNJson();                    // 紧凑格式
string json = obj.ToNJson(formatting: true);    // 缩进格式
string json = obj.ToNJson(customSettings);      // 自定义设置

// 反序列化
var entity = json.ToNJsonEntity<MyType>();
var entity = json.ToNJsonEntity<MyType>(customSettings);

Protobuf 序列化 (protobuf-net)

用于高性能网络传输的二进制序列化。

// 序列化: 对象 -> byte[]
byte[] protoBytes = obj.ToProtobuf();

// 反序列化: byte[] -> 类型化对象
var entity = protoBytes.ToProtobufEntity<MyType>();

要求: 目标类必须使用 [ProtoContract][ProtoMember(N)] 特性装饰。

在 Snet Core 中的使用:

// AddressValue 数据 -> Protobuf 传输
var dict = new ConcurrentDictionary<string, AddressValue>();
var protoObj = dict.GetSimplifyProtobuf();  // AddressValueSimplifyProtobuf
byte[] wireData = protoObj.ToProtobuf();

// 接收并反序列化
AddressValueSimplifyProtobuf received = wireData.ToProtobufEntity<AddressValueSimplifyProtobuf>();

XML 序列化

ExtendMethod (简单的一行调用)

// 序列化: 对象 -> XML 字符串 (输入为 null 时返回 null)
string? xml = obj.ToXml();

// 反序列化: XML 字符串 -> 对象 (默认 UTF-8)
var entity = xmlString.ToXmlEntity<MyType>();

// 指定编码
var entity = xmlString.ToXmlEntity<MyType>(Encoding.GetEncoding("GB2312"));

XmlHandler (功能完整)

用于复杂 XML 操作的实例类。

方法 描述
XmlSerialize(object, Encoding) 序列化对象为 XML 字符串
XmlDeserialize<T>(string, Encoding?) 反序列化 XML 字符串为对象
CreateXmlDocument() 创建 XML 文档(无需文件)
Read(string xmlFile) 从文件读取 XML 文档
Insert(string xmlFile, string nodePath, string element, string? value, IDictionary<string,string>? attrs) 插入元素/属性
Update(string xmlFile, string nodePath, string? value, IDictionary<string,string>? attrs) 更新元素/属性
Delete(string xmlFile, string nodePath, string? attribute) 删除元素/属性
GetDataSet(string xmlFile) 将 XML 读入 DataSet
GetTable(string xmlFile, string tableName) 按名称提取 DataTable
GetTableCell(string xmlFile, string tableName, int row, int col) 单单元格值
GetNodeValue(string xmlFile, string nodePath) 通过 XPath 读取节点值
ReadXML<T>(string path) 反序列化 XML 文件为对象
WriteXML<T>(string path, T obj, string rootName?, Encoding?) 序列化对象到 XML 文件
SerializeToXmlStr<T>(T obj) 序列化为 XML 字符串

安全性: 所有 XmlDocument 实例均使用 XmlResolver = null 以防止 XXE 攻击。序列化器通过 ConcurrentDictionary<Type, XmlSerializer> 缓存以防止内存泄漏。


字节操作 (ByteHandler)

静态类,包含 100+ 字节级操作方法。

Hex 转换

方法 签名 描述
HexToBytes string -> byte[] Hex 字符串转字节数组
HexToStr byte[] -> string 字节数组转 Hex 字符串
ByteArrayToHexString byte[] -> string 另一种 Hex 格式化
StringToByteArray string -> byte[] Hex 字符串转字节

CRC / 校验和

方法 描述
CalculateCrc(byte[]) Modbus CRC16 (查表法, XModem 变体, 多项式 0xC0C1)
calc_crc_16(UInt16 polynomials, byte[] buffer) CRC16 自定义多项式变体
calc_sum_16(byte[] buffer) 16 位算术求和校验
calc_xor(byte[] buffer) XOR 校验
CalculateLrc(byte[] data)byte 纵向冗余校验 (LRC)

字节数据操作

方法 描述
ByteDataSplit(byte[] data, int ReserveLocation, int SplitCount) 按索引和数量分割字节数组
ByteListSegmentation(byte[] data, int Segmentation) 按块大小分割字节数组
BoolArrayToByte(bool[]) 布尔数组转字节
ByteToBoolArray(byte[]) 字节数组转布尔数组
AsciiArrayToByteArray(byte[]) ASCII 字节转数值
ByteArrayToAsciiArray(byte[]) 数值字节转 ASCII
BoolOnByteIndex(byte, int index) 读取指定位置的位
SetBoolOnByteIndex(byte, int index, bool) 设置指定位置的位
ArrayExpandToLength(byte[], int) 填充/截断到指定长度
ArraySplitByLength(byte[], int) 按固定大小分块
BytesReverseByWord(byte[]) 按字反转字节

数值转换

方法 描述
IntToBytes(int value) / ByteToInt(byte[] data, bool IsLittleEndian = false) Int <-> byte[]
GetDouble(ushort,ushort,ushort,ushort) 4 个 ushort -> IEEE 754 double
GetSingle(ushort,ushort) 2 个 ushort -> IEEE 754 float
GetUInt32(ushort,ushort) 2 个 ushort -> uint32

CoreExtend 字节工具 (Snet.Core)

方法 签名 描述
WriteGetBytes object -> byte[] 数值 (short/ushort/int/uint/long/ulong/double/float) 通过 BitConverter 转字节
WriteGetBytes string + Encoding -> byte[] 字符串转编码字节
ReadGetLength DataType -> ushort 类型字节大小: Long/Double/Ulong -> 8, Int/Float/Uint -> 4, Short/Ushort -> 2, 其他 -> 0
GetEncoding EncodingType? -> Encoding null -> UTF8, 否则 Encoding.GetEncoding(codePage)
GetEncoding EncodingType -> Encoding 非空重载
GetDefaultEncodingWrite ConcurrentDictionary<string,object> + EncodingType? -> ConcurrentDictionary<string,(object,EncodingType?)> 为写入值附加编码

AES 加密

256 位 AES-CBC,通过 System.Security.Cryptography.Aes

// 加密 (返回 Hex 字符串)
string encrypted = plainText.AESEncrypt();                      // 默认密钥/向量
string encrypted = plainText.AESEncrypt(key: myKey, iv: myIV);  // 自定义

// 解密 (输入: Hex 字符串, 输出: 明文)
string decrypted = encrypted.AESDecrypt();                      // 默认密钥/向量
string decrypted = encrypted.AESDecrypt(key: myKey, iv: myIV);  // 自定义

默认密钥: "sDhibwYX7EkqG6b6GfcO3/ft1FBeYb+Gdml4lhKXJ/o=" (SHA256 哈希为 32 字节) 默认向量: "zRDPEQHreJ2d7tANOdGoIQ==" (截断/填充为 16 字节)


哈希

全部返回小写 Hex 字符串。

方法 输入 描述
ComputeSHA256() byte[] / string / FileStream SHA256 哈希
ComputeSHA1() byte[] / string / FileStream SHA1 哈希 (不安全)
ToMD5() string MD5 哈希 (不安全, 用于文件校验)
string hash1 = "hello world".ComputeSHA256();
string hash2 = File.OpenRead("file.dat").ComputeSHA256();
string hash3 = bytes.ComputeSHA1();
string hash4 = "data".ToMD5();

Base64

// 编码
string b64 = bytes.ToBase64();           // byte[] -> Base64 字符串
string b64 = "text".UTF8ToBase64();      // 字符串 -> UTF8 字节 -> Base64

// 解码
byte[] bytes = b64Str.Base64ToBytes();   // Base64 字符串 -> byte[]
string text = b64Str.Base64ToUTF8();     // Base64 -> UTF8 字符串

字节序

方法 描述
bytes.ReverseBytes() 反转字节数组 (大端<->小端)
value.ReverseEndianness<T>() 反转值类型字节序
array.ReverseEndianness<T>() 反转数组中每个元素
value.ToNetworkByteOrder<T>() 转换为大端序 (在大端系统上不操作)
value.FromNetworkByteOrder<T>() 从大端序转换为主机字节序
IsLittleEndian (静态属性) BitConverter.IsLittleEndian

结构体封送

// 字节数组 -> 结构体 (C/C++ 互操作)
var myStruct = byteArray.ByteArrayToStructure<MyStruct>(offset: 0);

// 结构体 -> 字节数组
byte[] bytes = myStruct.StructureToByteArray();

还支持泛型 ToBytes<T>() / ToValue<T>() / ToValueArray<T>(),使用 Marshal.SizeOfGCHandle 钉住。


深拷贝

// 通过 JSON 往返的泛型深拷贝
var copy = original.DeepCopy<MyType>();

// 浅数组拷贝 (值类型 = 深拷贝, 引用类型 = 浅拷贝)
var arr = source.CopyArray();

文件 I/O (FileHandler)

方法 描述
FileToString(string path, Encoding?, bool removeBom) 读取文件 -> 字符串 (64KB 缓冲区)
FileToStringAsync(string path, Encoding?, bool removeBom) 异步读取文件 -> 字符串
StringToFile(string path, string content) 写入字符串 -> 文件
StringToFileAsync(string path, string content) 异步写入字符串 -> 文件
ConvertToBinary(string path) 文件 -> 二进制数据
GetFolderPath(string path, bool create) 提取目录路径,自动创建
GetFileName(string path) 提取含扩展名的文件名

验证工具

ExtendMethod 中丰富的验证方法:

方法 描述
IsJson() 验证 JSON (string / ReadOnlySpan / ReadOnlySequence)
IsMatch(pattern) 正则匹配,可选忽略大小写
IsNumber() / IsInteger() 数值验证
IsEmail() 邮箱格式
IsURL() URL 格式
IsIPv4() / IsIPv6() IP 地址验证
IsGuid() / IsGuid(out Guid) GUID 格式检查
IsDateTime() / IsDateTime(out DateTime) 日期/时间解析
IsIDCard() / IsIDCard18() / IsIDCard15() 中国身份证号验证
IsMobilePhoneNumber() 中国手机号码
IsTelePhoneNumber() 中国座机号码
IsZipCode() 中国邮政编码
IsHexadecimal() Hex 字符串验证
IsLongitude() / IsLatitude() 地理坐标

其他工具

类别 方法
URL 编码 UrlEncode(), UrlDecode()
HTML 编码 HtmlEncode(), HtmlDecode()
字符串拼接 JoinList<T>(split, prefix, suffix)
SQL 助手 ToSqlIn(), JoinSqlIn<T>()
GUID 助手 ToUpperNString(), ToLowerNString(), ToNString()
DateTime 格式化 ToLongDate(), ToDateString(), ToDateTimeString(), ToShortDateTimeString(), GetDate(), GetDateDetails()
Unix 时间戳 DateTime.ToInt() (转 Unix 秒), int.ToDateTime() (从 Unix 秒转换)
对象比较 Comparer<T>(other, ignoreProperties?) -- 深度对象差异比较
枚举助手 EnumToList<T>(), GetDescription(), EnumValueToEnumObj<T>(), EnumKeyToEnumObj<T>()
类型转换 ToInt(), ToLong(), ToDecimal(), ToDouble(), ToDateTime(), ToULong(), ToUInt()
字节数组 ToBytes() (结构体 / 字符串), ToValue<T>(), ToUTF8String(), ToEncodeString()
延时 DelayUs(double) / DelayUs(int) -- 微秒级自旋等待

代码示例

序列化往返 (JSON)

var address = new Address("Line1", details, DateTime.Now);

// JSON 往返
string json = address.ToJson(formatting: true);
Address? restored = json.ToJsonEntity<Address>();

// Protobuf 往返
byte[] proto = address.ToProtobuf();
Address protoRestored = proto.ToProtobufEntity<Address>();

// XML 往返
string? xml = address.ToXml();
Address? xmlRestored = xml.ToXmlEntity<Address>();

// Newtonsoft 往返
string njson = address.ToNJson(formatting: true);
Address? nRestored = njson.ToNJsonEntity<Address>();

字节转换管道

// 数值 -> 字节 (用于 PLC 写入)
short value = 1234;
byte[] bytes = ((object)value).WriteGetBytes();  // [0xD2, 0x04] (小端序)

// 字节 -> Hex 字符串
string hex = ByteHandler.ByteArrayToHexString(bytes);  // "D204"

// Hex 字符串 -> 字节
byte[] fromHex = ByteHandler.HexToBytes("D204");

// Modbus CRC
byte[] frame = [0x01, 0x03, 0x00, 0x00, 0x00, 0x01];
ushort crc = ByteHandler.CalculateCrc(frame);  // CRC16 结果

// 字符串 -> 编码字节 -> Hex
string text = "Hello Snet";
Encoding gb2312 = ((EncodingType?)EncodingType.GB2312).GetEncoding();
byte[] encodedBytes = text.WriteGetBytes(gb2312);

加密与哈希

// AES 加密/解密
string encrypted = "敏感数据".AESEncrypt();
string decrypted = encrypted.AESDecrypt();
// decrypted == "敏感数据"

// SHA256
string fileHash = File.OpenRead("config.json").ComputeSHA256();

// MD5 (文件校验)
string checksum = "hello".ToMD5();

深拷贝与比较

// 深拷贝
var cloned = originalAddress.DeepCopy<Address>();

// 深度比较 (忽略指定属性)
var (isEqual, differences) = address1.Comparer(address2, new[] { "Time", "CreationTime" });
if (!isEqual)
{
    foreach (var diff in differences)
        Console.WriteLine($"{diff.PropertyName}: {diff.Object1Value} != {diff.Object2Value}");
}