解决方案
如果我们需要手动填充每个成员变量,则可以使用FormatterServices按顺序检索与对象关联的变量类型的列表,就其涉及的原语进行概括。我必须在一个项目中执行此操作,在该项目中,我会遇到很多不同的消息类型,并且我绝对不想为每条消息编写序列化器/反序列化器。
这是我用来从byte []进行反序列化的代码。
public virtual bool SetMessageBytes(byte[] message) { MemberInfo[] members = FormatterServices.GetSerializableMembers(this.GetType()); object[] values = FormatterServices.GetObjectData(this, members); int j = 0; for (int i = 0; i < members.Length; i++) { string[] var = members[i].ToString().Split(new char[] { ' ' }); switch (var[0]) { case "UInt32": values[i] = (UInt32)((message[j] << 24) + (message[j + 1] << 16) + (message[j + 2] << 8) + message[j + 3]); j += 4; break; case "UInt16": values[i] = (UInt16)((message[j] << 8) + message[j + 1]); j += 2; break; case "Byte": values[i] = (byte)message[j++]; break; case "UInt32[]": if (values[i] != null) { int len = ((UInt32[])values[i]).Length; byte[] b = new byte[len * 4]; Array.Copy(message, j, b, 0, len * 4); Array.Copy(Utilities.ByteArrayToUInt32Array(b), (UInt32[])values[i], len); j += len * 4; } break; case "Byte[]": if (values[i] != null) { int len = ((byte[])values[i]).Length; Array.Copy(message, j, (byte[])(values[i]), 0, len); j += len; } break; default: throw new Exception("ByteExtractable::SetMessageBytes Unsupported Type: " + var[1] + " is of type " + var[0]); } } FormatterServices.PopulateObjectMembers(this, members, values); return true; }
大多数人使用.NET序列化(有更快的二进制文件和更慢的XML格式化程序,它们都依赖于反射并且在一定程度上可以容忍版本)
但是,如果我们想要最快(不安全)的方式,为什么不这样做:
写:
YourStruct o = new YourStruct(); byte[] buffer = new byte[Marshal.SizeOf(typeof(YourStruct))]; GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); Marshal.StructureToPtr(o, handle.AddrOfPinnedObject(), false); handle.Free();
读:
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); o = (YourStruct)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(YourStruct)); handle.Free();
例如:
在C++中,只要将指向流的指针转换为我要使用的数据类型即可。
Mystruct * pMyStrct = (Mystruct*)&SomeDataStream; pMyStrct->Item1 = 25; int iReadData = pMyStrct->Item2;
日期:2020-03-24 10:32:00 来源:oir作者:oir