赞
踩
首先明确一下什么是托管类型什么是非托管类型
托管类型一般可以认为是复杂类型,比如
- class MyObject
- {
- public int n1 = 0;
- public int n2 = 0;
- public String str = null;
- }
非托管类型一般指基础类型比如:sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal 或 bool
托管类型的数组序列化和非托管类型的字节数组序列化差别不大,总体来说就是托管类型相比非托管类型要指定内存布局,好在C#可以通过特性StructLayout来指定内存布局
非托管类型的序列化通常可使用静态类BitConverter的方法处理
而一个可用于托管类型字节数组序列化的代码大致可以是这样的,这段代码要确保开启了unsafe模式
- [StructLayout(LayoutKind.Sequential)]
- class MyObject
- {
- public int n1 = 0;
- public int n2 = 0;
- public String str = null;
- }
-
- static void Main(string[] args)
- {
-
- MyObject obj = new MyObject();
- obj.n1 = 1;
- obj.n2 = 24;
- obj.str = "Some String";
-
- byte[] data1 = Struct2Bytes<MyObject>(obj);
- MyObject myObject2 = (MyObject)Bytes2Struct<MyObject>(data1, typeof(MyObject));
- }
- // 字节数组序列化
- public static unsafe byte[] Struct2Bytes<T>(Object obj)
- {
- int size = Marshal.SizeOf(obj);
- byte[] bytes = new byte[size];
- fixed (byte* pb = &bytes[0])
- {
- Marshal.StructureToPtr(obj, new IntPtr(pb), true);
- }
- return bytes;
- }
- // 字节数组反序列化
- public static unsafe Object Bytes2Struct<T>(byte[] bytes, Type type)
- {
- fixed (byte* pb = &bytes[0])
- {
- return Marshal.PtrToStructure(new IntPtr(pb), type);
- }
- }
[StructLayout(LayoutKind.Sequential)]可以将对象的成员按照它们在被导出到非托管内存时出现的顺序依次布局。 这些成员根据在 Pack 中指定的封装进行布局,并且可以是不连续的。
而LayoutKind也有其他的处理方法,比如根据每个变量自己分配内存布局,MyObject类写成这样也是可以的
- [StructLayout(LayoutKind.Explicit)]
- class MyObject
- {
- [FieldOffset(0)] public int n1 = 0;
- [FieldOffset(4)] public int n2 = 0;
- [FieldOffset(8)] public String str = null;
- }
当然还有其它的方法,使用BinaryFormatter也可以完成这样的操作,但是有一定的缺点,这样字节序列出来的字节数组最小也要256字节,诸如需要发信仅10字节时会造成浪费,增大网络流量
这种方法需要Serializable特性
- [Serializable]
- class MyObject
- {
- public int n1 = 0;
- public int n2 = 0;
- public String str = null;
- }
-
- static void Main(string[] args)
- {
-
- BinaryFormatter formatter = new BinaryFormatter();
- MemoryStream memeryStream = new MemoryStream();
-
- MyObject obj = new MyObject();
- obj.n1 = 1;
- obj.n2 = 24;
- obj.str = "Some String";
-
- // 至少有256字节,如果只有10字节但发送时却需要256字节,增大网络流量
- formatter.Serialize(memeryStream, obj);
- byte[] data = memeryStream.GetBuffer();
-
- // 二进制反序列化成对象
- MemoryStream st = new MemoryStream(data);
- MyObject myObject1 = (MyObject)formatter.Deserialize(st);
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。