0

I have to create an instance of an arbitrary value type from the bytes stored at some given offset in an array of bytes (for example, if type is int, 4 bytes shall be taken). I know I can easily do it using pointers to fixed objects, but I don't want to have unsafe code. So I try the following code (sanity checks were stripped):

public object GetValueByType(System.Type type, byte[] byteArray, int offset)
{
    int size = System.Runtime.InteropServices.Marshal.SizeOf(type);
    MemoryStream memoryStream = new MemoryStream();
    memoryStream.Write(byteArray, offset, size);
    memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
    BinaryFormatter binaryFormatter = new BinaryFormatter();
    object obj = (object)binaryFormatter.Deserialize(memoryStream);
    return obj;
}

But this code breaks at binaryFormatter.Deserialize.

How may I fix the above code (or achieve the same purpose in any other way)?

Chris Mantle
  • 6,595
  • 3
  • 34
  • 48
Ofer
  • 423
  • 6
  • 11
  • 2
    *But this code breaks at "binaryFormatter.Deserialize"* How does it break? Exception? Compile error? Incorrect program output? – Chris Mantle Jun 10 '14 at 11:17
  • 1
    `BinaryFormatter` is **not** simply "read an arbitrary value type from memory". It would only work if the original data was *stored* via `BinaryFormatter`. So: how was the original data stored? – Marc Gravell Jun 10 '14 at 11:17
  • 2
    Incidentally, it sounds like what you actually want is something half-way between `BitConverter` and `BinaryReader` – Marc Gravell Jun 10 '14 at 11:18
  • Marc: The byte array stores an arbitrary sequence of bytes received from some communication port. – Ofer Jun 10 '14 at 11:40
  • Chris: SerializationException, "End of Stream encountered before parsing was completed", HResult 0xe0434352. – Ofer Jun 10 '14 at 11:48

1 Answers1

1

Eventually found a solution here (see answer 50), and that's the final code for your convenience:

    public object GetValueByType(Type typeOfReturnedValue, int offsetInDataSection)
    {
        GCHandle handle = GCHandle.Alloc(this.byteArray, GCHandleType.Pinned);
        int offset = <some desired offset>;
        IntPtr addressInPinnedObject = (handle.AddrOfPinnedObject() + offset);
        object returnedObject = Marshal.PtrToStructure(addressInPinnedObject, typeOfReturnedValue);
        handle.Free();
        return returnedObject;
    }

This way my code remains without any unsafe code. Isn't it great?!

Community
  • 1
  • 1
Ofer
  • 423
  • 6
  • 11