简体   繁体   中英

Initialize struct with byte array based on header type

I have several structs in my file. I want to pass a byte array and initialize the the struct. I have tried struct to byte array conversion and vice versa but I am getting errors like "Attempted to read or write protected memory". So I thought passing byte array to initialize the struct might be more efficient. My problem is that one part of structure is dependent of first byte type. So how do I assign another structure to it?

Here is the code:

[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];
    }
}

Don't roll your own: Use the infrastructure .Net and the CLR provides for you.

If you need to interoperate with unmanaged code, you need to learn about P/Invoke and marshalling:

If you are interoperating with other managed code, you need to read about serialization . More at

You can use stock binary serialization, or roll you own. In either case, you want your object to be ISerializable , which requires just one method be implemented for serializing your object into a bytestream: void GetObjectData( SerializationInfo info , StreamingContext context ) .

And [implies] a corresponding constructor for deserializing the bytestream back into an object instance having the signature constructor( SerializationInfo information, StreamingContext context) .

For example:

[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
  }
  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM