c#自带各种方便的序列化功能,例如可以序列化类为json,序列化为XML。
我对C#了解甚少,最近需要做一个unity3D服务器和c++客户端网络通信的功能,所以实现了一个简略序列化函数,搓作留此纪念。
实现如下:
首先实现一个动态缓存区,可以自动增大,具有增加数据和获取数据接口,用于进行序列化时使用
该类使用泛型实现
Dynamical.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NetWork.NetWork
{
public class Dynamical<T>
{
public Dynamical()
{
buff = new List<T>(10);
cur_len = 0;
max_len = 10;
}
public int GetSize()
{
return cur_len;
}
public void ReSet()
{
cur_len = 0;
}
public void AddData(T[] data, int size)
{
for (int i = cur_len; i < cur_len + size; i++)
{
if (i < max_len)
{
buff[i] = data[i - cur_len];
}
else
{
buff.Add(data[i - cur_len]);
}
}
cur_len += size;
max_len += buff.Count;
}
public void RemoveData(int start, int size)
{
if (start < 0 || size < 0 || start +size > cur_len)
{
return;
}
for (int i = 0; i < cur_len - start - size; i++)
{
buff[i + start] = buff[start + size + i];
}
cur_len -= size;
}
void GetData(ref T[] data, int start, int size)
{
if (start < 0 || size <= 0 || start + size > cur_len)
{
return;
}
T[] tmp = new T[size];
for (int i = 0; i < size; i ++)
{
tmp[i] = buff[i + start];
}
data = tmp;
}
List<T> buff;
int cur_len;
int max_len;
}
}
1、首先实现一个基类,有两个虚函数,Serializable()、DeSerializable()需要子类去实现
2、再实现一个通用的SerializableBase()、DeSerializableBase()函数,可以序列化反序列化基本类型
当然可以在这个两个函数中增加其他非基本类型的序列化,反序列化,那么子类就只需要不断递归调用Serializable,
SerializableBase就可以实现序列化。DeSerializable,DeSerializableBase实现反序列化对复杂类型也手到擒来。
Serialization.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NetWork.NetWork
{
public class Serialization
{
public virtual void Serializable(ref Dynamical<byte> buff)
{
// 子类继承
}
public virtual void DeSerializable(ref byte[] buff, ref int offset, int size)
{
// 子类继承
}
public void SerializableBase(ref Dynamical<byte> buff, object obj)
{
if (obj is bool)
{
buff.AddData(BitConverter.GetBytes((bool)obj), sizeof(bool));
}
else if (obj is int)
{
buff.AddData(BitConverter.GetBytes((int)obj), sizeof(int));
}
else if (obj is float)
{
buff.AddData(BitConverter.GetBytes((double)obj), sizeof(float));
}
else if (obj is double)
{
buff.AddData(BitConverter.GetBytes((double)obj), sizeof(double));
}
else if (obj is char)
{
buff.AddData(BitConverter.GetBytes((char)obj), sizeof(char));
}
}
public object DeSerializableBase(Type type, ref byte[] buff, ref int offset, int size)
{
dynamic obj = null;
if (type == typeof(bool))
{
offset += sizeof(bool);
if (offset <= size)
obj = BitConverter.ToBoolean(buff, offset);
}
else if (type == typeof(int))
{
offset += sizeof(int);
if (offset <= size)
obj = BitConverter.ToInt32(buff, offset);
}
else if (type == typeof(double))
{
offset += sizeof(double);
if (offset <= size)
obj = BitConverter.ToDouble(buff, offset);
}
else if (type == typeof(float))
{
offset += sizeof(double);
if (offset <= size)
obj = BitConverter.ToDouble(buff, offset);
}
else if (type == typeof(char))
{
offset += sizeof(char);
if (offset <= size)
obj = BitConverter.ToChar(buff, offset);
}
return obj;
}
}
public class ListNode : Serialization
{
public int node_id;
public override void Serializable(ref Dynamical<byte> buff)
{
SerializableBase(ref buff, node_id);
}
public override void DeSerializable(ref byte[] buff, ref int offset, int size)
{
node_id = (int)DeSerializableBase(node_id.GetType(), ref buff, ref offset, size);
}
}
public class ChildClass : Serialization
{
public int id;
public char c;
public double d;
public List<ListNode> list;
public override void Serializable(ref Dynamical<byte> buff)
{
SerializableBase(ref buff, id);
SerializableBase(ref buff, c);
SerializableBase(ref buff, d);
int count = list.Count;
SerializableBase(ref buff, count);
for (int i = 0; i < count; i++)
{
list[i].Serializable(ref buff);
}
}
public override void DeSerializable(ref byte[] buff, ref int offset, int size)
{
id = (int)DeSerializableBase(id.GetType(), ref buff, ref offset, size);
c = (char)DeSerializableBase(c.GetType(), ref buff, ref offset, size);
d = (double)DeSerializableBase(d.GetType(), ref buff, ref offset, size);
int count = 0;
size = (int)DeSerializableBase(count.GetType(), ref buff, ref offset, size);
for (int i = 0; i < count; i++)
{
ListNode node = new ListNode();
node.DeSerializable(ref buff, ref offset, size);
}
}
}
}
test.cs
private void Form1_Load(object sender, EventArgs e)
{
ChildClass c = new ChildClass();
Dynamical<byte> dynamical = new Dynamical<byte>();
c.Serializable(ref dynamical);
byte[] buff = null;
dynamical.GetData(ref buff, 0, dynamical.GetSize());
ChildClass c1 = new ChildClass();
int offset = 0;
c1.DeSerializable(ref buff, ref offset, buff.Count());
}
二、缺点
每个子类都要实现DeSerializable,Serializable 函数,容易出错,编码也不方便。比起原生的json,xml序列化。不过传输过程中占用的消耗小,适用于网路传输。