项目地址:https://sourceforge.net/projects/sharpserialization/
我们的实际工作中经常会遇到跨语言的交互,如Java-C#-C++等,大部分情况下通过Xml、Json数据交换等协议可以很好的处理对象的交互,但有时我们希望数据流变得更小,性能变得更好,但同时又不想对现有程序做过多修改或者不想对每个协议对象编写特定的代码,这时,一个良好的二进制序列化器是自然的一个考虑,对于.Net语言间的交互,Framework自带的序列化器是自然也很好的选择,但当我们相同Java交互时又会力不从心了。SharpSerialization就是为了应付此种局面提出的。
SharpSerialization是一个轻量的序列化/反序列化器,可方便简单的用于.net对象的序列化,反序列化,本项目的目标并不是替代Framework的序列化系统,也并不是为了造*而造*,仅用于演示序列化系统的基本原理。本项目用于学习研究目的,并未经过严格测试,性能并不是项目的考虑要素(如对反射部分可使用EMIT等技术代替等),因此,请不要在实际项目中直接应用; 需要的朋友可以此为基础优化然后使用。
SharpSerialization的序列化协议如下:
一、 类型系统
类型 | 值 | 说明 |
BOOLEAN | 0 |
1=true; 0=false; |
INT8 | 1 | sbyte |
UINT8 | 2 | byte |
INT16 | 3 | short |
UINT16 | 4 | ushort |
INT32 | 5 | int |
UINT32 | 6 | uint |
INT64 | 7 | long |
UINT64 | 8 | ulong |
FLOAT | 9 | float |
DOUBLE | 10 | double |
DECIMAL | 11 | decimal以double值序列化。如需以原值序列化,请修改代码,把decimal处理为非内置类型 |
DATETIME | 12 | 以DateTime.Ticks值序列化 |
STRING | 13 | 7-bits编码长度+字符串的UTF-字节流 |
OBJECT | 14 | class/struct |
NULL | 15 | null |
MASK_ARRAY | 16 | 数组标志位,与其他简单类型通过逻辑或组成数组类型。 如int[] = INT32 | Array = 0x6 | 0x80; double[] = DOUBLE | Array = 0x0b | 0x80; |
二、二进制序列化器流协议
默认提供的二进制序列化器BinarySerializer同时提供序列化和反序列化的能力,以二进制流的形式序列化/反序列化对象。
注意:本协议流并未处理数据校验等,如需应用实际项目,请自行添加。
数据协议:
1、 对于内置类型(BOOLEAN - STRING),直接写入类型值+类型的实际值数据。如Int32值10,依次写入数据为:
> 1字节类型值:5
> 4字节INT32值(Little-Endian):10
2、 对于非内置类型,格式为:
> 1字节类型OBJECT值:14
> 类型名称字符串:Type.FullName,Assembly.Name
> 8字节ObjectID,详见下文说明
> 4字节类型的成员个数(INT32)
> 依次写入每个成员的名称、值
3、 对于数组类型,格式为:
> 1字节数组类型值:MASK_ARRAY | 基础类型值。
> 类型名称字符串:Type.FullName,Assembly.Name。
> 4字节数组的维数(INT32)。
> 依次写入每个维度的秩(INT32)。
> 依次写入每个元素。
三、用法示例:
1 using SharpSerialization;
2 using System;
3 using System.Collections.Generic;
4 using System.IO;
5 using System.Text;
6
7 class MyObject
8 {
9 int m_id;
10 string m_name;
11
12 MyObject2 m_crossReference;
13
14 public int ID
15 {
16 get { return m_id; }
17 }
18 public string Name
19 {
20 get { return m_name; }
21 }
22
23 public MyObject2 CrossReference
24 {
25 get { return m_crossReference; }
26 set { m_crossReference = value; }
27 }
28
29 public MyObject(int id, string name, MyObject2 cro)
30 {
31 m_id = id;
32 m_name = name;
33 m_crossReference = cro;
34 }
35 }
36
37 class MyObject2
38 {
39 string m_name;
40 MyObject m_interObj;
41
42 public string Name
43 {
44 get { return m_name; }
45 }
46
47 public MyObject InterObj
48 {
49 get { return m_interObj; }
50 }
51
52 public MyObject2(string name, MyObject obj)
53 {
54 m_name = name;
55 m_interObj = obj;
56 }
57 }
58
59
60 class Serialization
61 {
62
63 static void Main(string[] args)
64 {
65 MyObject obj = new MyObject(1, "MyObject", null);
66 MyObject2 obj2 = new MyObject2("MyObject2", obj);
67 obj.CrossReference = obj2;
68
69
70 using (MemoryStream ms = new MemoryStream())
71 {
72 BinaryStream bs = new BinaryStream(ms);
73
74 BinarySerializer<BinaryStream> serializer = new BinarySerializer<BinaryStream>(bs);
75
76 serializer.Serialize(obj);
77
78 ms.Seek(0, SeekOrigin.Begin);
79
80 MyObject nOb = (MyObject)serializer.Deserialize();
81
82 Console.WriteLine(nOb.ID);
83 Console.WriteLine(nOb.Name);
84 Console.WriteLine(nOb.CrossReference.Name);
85 }
86
87 Console.ReadLine();
88 }
89 }