C# - 结构系列化(C# - struct serialization)

2019-10-22 04:45发布

我有一个小的类,我想用序列化结构。 我想知道两件事情:

  • 性能问题。 因为我传递Object -它通过只是一个参考,而不是结构的副本? 而且,由于我返回类型的对象T也只是通过一个参考?

  • 正确性问题。 将所有结构此序列化工作? 我的意思是 - 是否有可能在那里这些方法都不行?

     public static byte[] ToByteArray(Object obj) { int size = Marshal.SizeOf(obj); byte[] arr = new byte[size]; IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(obj, ptr, true); Marshal.Copy(ptr, arr, 0, size); Marshal.FreeHGlobal(ptr); return arr; } public static T ToStructure<T>(byte[] arr) where T : new() { T str = new T(); int size = Marshal.SizeOf(str); IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.Copy(arr, 0, ptr, size); str = (T)Marshal.PtrToStructure(ptr, str.GetType()); Marshal.FreeHGlobal(ptr); return str; } 

多谢你们!

编辑

我现在规定,这些都是结构。 什么都没有,现在复制?

    public static byte[] ToByteArray<T>(ref T str) where T : struct
    {
        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }

    public static T ToStructure<T>(byte[] arr) where T : struct
    {
        T str = default(T);

        int size = Marshal.SizeOf(str);
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.Copy(arr, 0, ptr, size);
        str = (T)Marshal.PtrToStructure(ptr, str.GetType());
        Marshal.FreeHGlobal(ptr);

        return str;
    }

Answer 1:

  1. 这将不会正确地序列的引用(即,非原语和非结构类型的任何字段)。
  2. 它不包括数据类型
    • 这使得它不适合情况下,当不是所有的类型都事先知道或因为序列化时某些类型略有变化。
  3. (次要) ToStructure不验证二进制数据

为什么不学习重新发明轮子之前,现有的解决方案? 该序列化准则的文章说,有在具有不同的特点又适合用于不同目的的.NET框架实现系列化3种技术。

下面是作为例子给出最简单的,第3技术的例子在.NET对象序列化的文章。 它的存在是为了重建一个对象具有完全相同的类型和与原内部数据(这意味着,系列化包括它引用的对象)。
(该代码是在目前的IronPython我希望这是足够的可阅读理解这是怎么回事)

>>> l=System.Collections.Generic.List[System.Drawing.Point]\
([System.Drawing.Point(*(random.randint(1,1000) for _ in range(2))) for _ in range(5)])
>>> l
List[Point]([<System.Drawing.Point object at 0x0000000000000233 [{X=491,Y=874}]>
, <System.Drawing.Point object at 0x0000000000000234 [{X=819,Y=595}]>, <System.D
rawing.Point object at 0x0000000000000235 [{X=456,Y=625}]>, <System.Drawing.Poin
t object at 0x0000000000000236 [{X=583,Y=29}]>, <System.Drawing.Point object at
0x0000000000000237 [{X=329,Y=212}]>])
>>> szr=System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
>>> stm=System.IO.MemoryStream()
>>> szr.Serialize(stm,l)
>>> stm.Length
481L
>>> bytes=stm.GetBuffer()
>>> s=''.join(chr(b) for b in bytes)
>>> s
u'\x00\x01\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x0c\x02\x
00\x00\x00QSystem.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f
5f7f11d50a3a\x04\x01\x00\x00\x00\x8c\x01System.Collections.Generic.List`1[[Syste
m.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToke
n=b03f5f7f11d50a3a]]\x03\x00\x00\x00\x06_items\x05_size\x08_version\x04\x00\x00\
x16System.Drawing.Point[]\x02\x00\x00\x00\x08\x08\t\x03\x00\x00\x00\x05\x00\x00\
x00\x00\x00\x00\x00\x07\x03\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x04\
x14System.Drawing.Point\x02\x00\x00\x00\x05\xfc\xff\xff\xff\x14System.Drawing.Po
int\x02\x00\x00\x00\x01x\x01y\x00\x00\x08\x08\x02\x00\x00\x00\xeb\x01\x00\x00j\x
03\x00\x00\x01\xfb\xff\xff\xff\xfc\xff\xff\xff3\x03\x00\x00S\x02\x00\x00\x01\xfa
\xff\xff\xff\xfc\xff\xff\xff\xc8\x01\x00\x00q\x02\x00\x00\x01\xf9\xff\xff\xff\xf
c\xff\xff\xffG\x02\x00\x00\x1d\x00\x00\x00\x01\xf8\xff\xff\xff\xfc\xff\xff\xffI\
x01\x00\x00\xd4\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'


Answer 2:

  1. 它会复制。 这就是所谓的“拳”。 传递给一个struct S上参考唯一的方法是有一个参数声明为ref S.
  2. 它不会处理嵌套的东西,如成员是数组,字符串或任何类类型。

FYI有了泛型可以约束的方法只适用于与结构“其中T:结构”



文章来源: C# - struct serialization