这篇文章不会介绍.NET框架系统本身提供的二进制序列化 当然也不会存在P/INVOKE方式定长序列化 这里的二进制序列化主要用于解决跨语言的问题 这里的实际上是完全的小端模式,双字节描述数组长度的一种形式 它不具备任何描述信息如果非要说具备那就是数组长度需要占用两个字节 当然具备升级版的二进制序列化是可以控制是单字节或双子节表示长度的问题 但不是本文需要讨论的问题
它可以序列化复杂的嵌套对象类型 这是为了方便序列化的内容可以通过TCP/UDP协议进行传输 研发的目的主要是由于在新版的 逻辑服务器通信层框架层与两类客户端通信层框架层 提供一套尽可能让开发人员从繁琐的解包封包中解脱出来 所以在我们的逻辑服务器框架层是具备两套序列化算法(大端、小端)
先注明这套序列化机制不会进行位运算可能造成一定流量浪费 当然在我们所遭遇的场景内需要位运算之处并不多 那么下面我们先看看它在二进制流中如何表示
上面有个大方框第一个则表示需要被序列化成对象的二进制流块 第二个大方框则表示其中一个对象成员的二进制序列化流块 两者相互级联达到深度二进制对象序列化与反序列化
在第二个大方框中你可以看到具备一个[len]后面则是[object...]这表示这个数组对象具备多少个成员需要被序列化 是一个描述性质的产物 这个对象可以是基本类型可以是一个对象 但值得一提的地方在于[len]如果等于-1则表示null个元素
从上图中你可能很难会发现一个反序列化差异性 的确二进制流被全部被反序列化成对象 但a.d与c.d的结果出现了不同这就是为什么呢?
显然我们需要去刨根问底才能明白究竟是怎么回事 在反序列化的过程中如果遇见IList<T>的类型是通过List<T>去装载容器数据这有些区别 而如果你把一个固定数组放入IList<T>类的属性 那么在反序列二进制的过程中则会出现这种问题 先声明这并不会影响你正确使用序列化
那么对于数组的序列化它支持那些类型,我不建议你定义List<T>类型属性 虽然它支持这种数组序列 但对于序列化的固态规范我认为是有必要的 而最佳通用的形式则是IList<T>与T[]
对于byte[]这种类型它是经过特殊优化的,速度会很快但IList<byte>、List<byte>两者数组类型却不一样因为它们之间的序列化的概念上将就是不同的 所以它并不具备相应的优化(这是个需要注意的点)
它可以支持IList<T>、List<T>、T[]类型数组 除此以外的类型数组不在支持队列显然没有任何必要 支持的过多对序列化本身开发则是一种负担 虽然的确并不会太难(就先这样吧 后面再谈论)
序列化算法源代码与示例代码的获取地址
GITHUB https://github.com/liulilittle/GNSS.Serialization
这是一段示例代码它展现了可以被支持二进制序列化的一些类型与定义规则
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GNSS.Serialization
{
class Program
{
public class A
{
public double a
{
get;
set;
}
public bool c
{
get;
set;
}
public string b
{
get;
set;
}
public IList<B> d
{
get;
set;
}
public byte[] f
{
get;
set;
}
public C[] t
{
get;
set;
}
public List<byte> buffer
{
get;
set;
}
public int[] x
{
get;
set;
}
public int[] y
{
get;
set;
}
public DateTime o
{
get;
set;
}
public ulong n
{
get;
set;
}
}
public class B
{
public int e
{
get;
set;
}
}
public class C
{
public string p { get; set; }
}
static void Main(string[] args)
{
A a = new A();
a.a = -321123123;
a.b = "hello world~!";
a.c = true;
a.d = new B[] { new B() { e = 112312414 } };
a.f = Encoding.ASCII.GetBytes("123124124");
a.t = new C[] { new C() { p = "闪烁" }, new C() { p = "超越" } };
a.buffer = new List<byte>() { 1, 2, 3, 4, 5, 6 };
a.x = new int[0];
a.y = null;
a.o = DateTime.Now;
a.n = 0xFFFFFFFFFFFFFFFF;
byte[] buffer = BinaryFormatter.Serialize(a);
A c = BinaryFormatter.Deserialize<A>(buffer);
}
}
}