【问题标题】:Initialize struct with byte array based on header type根据标头类型使用字节数组初始化结构
【发布时间】:2014-03-06 18:36:20
【问题描述】:

我的文件中有几个结构。我想传递一个字节数组并初始化结构。我已经尝试过从结构到字节数组的转换,反之亦然,但我收到了诸如“尝试读取或写入受保护的内存”之类的错误。所以我认为传递字节数组来初始化结构可能更有效。我的问题是结构的一部分取决于第一个字节类型。那么如何为它分配另一个结构呢?

代码如下:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct Payload
{
    MessageTypeID ID1;   
    MessageTypeID ID2;  
    Byte[] PayloadData; 

    public Payload(byte[] payloadArray)
    {
        this.ID1 = (MessageTypeID) payloadArray[0];
        this.ID2 = (MessageTypeID) payloadArray[1];

        switch (this.ID1)
        {
            case MessageTypeID.TEMPERATURE:
                byte[] tempPayloadArray = new byte[payloadArray.Length - 2];
                Temperature temp = new Temperature(Array.Copy(payloadArray,2,tempPayloadArray,0,payloadArray.Length - 2);
                this.PayloadData = temp;  <== ERROR: Cannot convert Temperature to byte[]
                break;
            case MessageTypeID.LEVEL:
            .......
        }
    }
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Temperature
{
    Byte LocalTemp;         
    Int16 ExternalTemp1;                                  
    Int16 ExternalTemp2;   

    public Temperature(byte[] tempArray)
    {
        this.LocalTemp = tempArray[0];
        this.ExternalTemp1 = tempArray[1];
        this.ExternalTemp2 = tempArray[2];
    }
}
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Level
{
    Byte FluidLevel;        
    Int16 FreshnessTimer;   
    Byte CalibrationChannelReading; 

    public Level(byte[] levelArray)
    {
        this.FluidLevel = levelArray[0];
        this.FreshnessTimer = BitConverter.ToInt16(levelArray, 1);
        this.CalibrationChannelReading = levelArray[3];
    }
}

【问题讨论】:

  • 请不要在问题标题中包含有关所用语言的信息,除非没有它就没有意义。标记用于此目的。
  • 为什么要将 temp 分配给 PayLoadData?如果您的要求是您需要一个需要分配给表示结构数据的 PayLoadData 的新字节数组,那么让 Tempearate 和其他结构返回它表示的字节数组。 (如果所有结构都这样做,您可以将其保留在基类中)
  • 我想构造数组,如果有效负载是例如类型温度,然后字节被组织在正确的字段中。

标签: c# struct bytearray


【解决方案1】:

不要自己动手:使用 .Net 和 CLR 为您提供的基础架构。

如果需要与非托管代码互操作,则需要了解 P/Invoke 和编组:

如果您正在与其他托管代码进行互操作,则需要阅读有关serialization 的信息。更多在

您可以使用库存二进制序列化,或滚动您自己的。无论哪种情况,您都希望您的对象为ISerializable,这只需实现一种方法即可将您的对象序列化为字节流:void GetObjectData( SerializationInfo info , StreamingContext context )

并且[隐含]一个相应的构造函数,用于将字节流反序列化回具有签名constructor( SerializationInfo information, StreamingContext context)的对象实例。

例如:

[Serializable]
public class Widget : ISerializable
{
  public Widget( SerializationInfo serializationInfo , StreamingContext context )
  {
    // your rehydration logic here
  }
  public void GetObjectData( SerializationInfo info , StreamingContext context )
  {
    // your dehydration logic here
  }
  ...
}

【讨论】:

  • 我接受了这个作为答案,因为虽然我没有完全按照你的建议去做,但我确实在我的结构中使用了 Serializable 和 OptionalField 以使其按我想要的方式工作。谢谢!
猜你喜欢
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多