【问题标题】:C# Marshalling vs SerializationC#编组与序列化
【发布时间】:2013-06-21 01:43:48
【问题描述】:

我有一个 C# 应用程序,它可以从/向 USB 读取/写入某些预定义协议的消息。所以我在这里至少有两个选择。一种是序列化/反序列化。另一个是元帅。一开始我选择了第一个选项,效果很好。但是在引入了越来越多的消息类型之后,我对每种消息类型的繁琐实现感到恼火,并且觉得 marshal 可能是更好的选择。我以前没用过元帅。这是正确的方法吗?我做了一些测试。我遇到的一个问题是当我有一个带有数组的结构时,如何写入它?如以下:-

    [StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable]
    public struct SomeData
    {
        /// char[15]
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
        public sbyte[] data;

        /// int[15]
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
        public int[] prob;
    }

似乎数据和概率都是引用,我必须新建一个对象才能使用它们,这对我来说听起来不太正确。我需要整个结构是一个连续的内存块,我认为 new 运算符不会为我这样做。

非常感谢任何建议

下面是我通过序列化做的。

    List<byte> rawData = new List<byte>();
    rawData.AddRange(BitConverter.GetBytes(ProtocolVersion));
    // 16 bytes for operator ID
    byte[] temp = new byte[16];
    Array.Copy(Encoding.ASCII.GetBytes(OperatorId), temp, OperatorId.Length > temp.Length ? temp.Length : OperatorId.Length);
    rawData.AddRange(temp);

    // 16 bytes for operator password
    Array.Clear(temp, 0, temp.Length);
    Array.Copy(Encoding.ASCII.GetBytes(OperatorPassword), temp, OperatorPassword.Length > temp.Length ? temp.Length : OperatorPassword.Length);
    rawData.AddRange(temp);

以下是我的编组方法

    static byte[] RawSerialize<T>(T obj)
    {
        if (obj == null)
        {
            return null;
        }

        int size = Marshal.SizeOf(obj);
        byte[] result = new byte[size];
        IntPtr buffer = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(obj, buffer, false);
        Marshal.Copy(buffer, result, 0, size);

        return result;
    }

【问题讨论】:

  • 有一些方法可以以通用的方式进行序列化和反序列化,只需很少的仪式。你能告诉我们你是怎么做的吗?
  • 另外,如果您能告诉我们更多关于为什么序列化不适合您,以及为什么您认为编组可能会更好,那就太好了。
  • 我已经添加了代码示例。我没有说它对我不起作用。只是因为我必须解析不同类型的消息。
  • 编组示例看起来不错。这基本上就是我在我目前正在编写的程序中所做的事情。那么你有什么疑问呢?
  • 我不熟悉编组,不安全的代码让我很紧张,尽管我是一名 C++ 程序员。在我帖子的后半部分,我说我在访问数组时遇到了一些问题。

标签: c# arrays serialization marshalling


【解决方案1】:

看来我只需要像下面这样新建一个数组就可以了。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class SomeData
{
    /// char[15]
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
    public byte[] data = new byte[15];

    /// int[15]
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
    public int[] prob = new int[15];
}

【讨论】:

    猜你喜欢
    • 2019-07-21
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 2013-11-12
    • 2010-12-29
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    相关资源
    最近更新 更多