1

Googling around this I am getting a lot of mixed results from old .NET versions and so on.

Given a message protocol like:

  • Bytes 0-1: Message Type ID
  • Byte 2: Message number
  • Byte 3: Payload size
  • Bytes 4...n-1: Payload data
  • Bytes n,n+1: Checksum

I want to write a C# class Message which can serialize and deserialize with byte[] which might ideally have as its core something like this (I use properties but members are just fine if it matters)

class Message
{
 public Int16 Type {get; set;}
 public byte Number {get; set;}
 public byte PayloadSize {get; set;}
 public byte[] Payload{get; set;}
 public Int16 CheckSum {get; set;}
}

Of course to write code to do this is easy enough but I know .NET does have some automatic (de)serialization functionality which would be nice to avoid coding errors in dull boiler-plate code. However I need to guarantee the ordering, etc so the protocol is followed.

Does modern .NET Framework (4.x) allow a way to automate this and if so, what is it? How is attribute ordering controlled for instance? And how would I actually instance and serialize objects from/to byte[]?

I should add, I know one could write this sort of thing using reflection, but a solution that is more work than the problem it solves isn't of great use. Neither am I keen on using some code library unless very well-tested, this is really a question about C# capabilities built-in.

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • what about BinarySerializer - see https://stackoverflow.com/questions/30918176/how-to-binary-serializer-custom-class – auburg Jan 09 '20 at 15:12
  • Use a struct with sequential layout: https://stackoverflow.com/questions/628843/byte-for-byte-serialization-of-a-struct-in-c-sharp. Don't think it'll work with your byte array though. – CodeCaster Jan 09 '20 at 15:38
  • @auburg no, you do not want to use `BinaryFormatter`, and you cannot in this scenario, because it has its own format. See for example https://stackoverflow.com/questions/5284641/should-i-still-use-binaryformatter-for-simple-serialization-in-net-4-0. You may mean `BinaryReader`, but that's exactly what the OP seems to want to avoid. – CodeCaster Jan 09 '20 at 15:48

1 Answers1

0

I was think of an overlay like this

    [StructLayout(LayoutKind.Explicit, Size = 128)]
    struct Message
    {
        [FieldOffset(0)]
        public byte[] data;
        [FieldOffset(0)]
        public Int16 Type;
        [FieldOffset(2)]
        public byte Number;
        [FieldOffset(3)]
        public byte PayloadSize;
        [FieldOffset(4)]
        public Int16 type;
        [FieldOffset(6)]
        public byte[] Payload;
        [FieldOffset(126)]
        public Int16 CheckSum;
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • And what if the payload has 0 bytes in it, or 121? – CodeCaster Jan 09 '20 at 15:43
  • If the payload is variable size than the CRC should be part of the Payload and not a separate property. – jdweng Jan 09 '20 at 15:47
  • That is what `PayloadSize` and `Bytes 4...n-1` seems to imply, and then this is indeed an option. The OP then needs code to obtain the checksum bytes from the payload, and remember to skip the last two bytes of the payload when wanting to read the payload. – CodeCaster Jan 09 '20 at 15:49
  • Having elements after a variable-sized element does rather mess this up though it is a real-life example. Seems a good solution in more rigid cases though. This is like a C union, interesting idea I hadn't considered at all to actually force it to be memory aligned rather than have automated serialization logic – Mr. Boy Jan 09 '20 at 16:25
  • I though about this a few days ago on another posting. Not sure why others haven't done this before. Usually the variable item is the last item (or there is a length before the variable item). These type structure were used a lot in unix and now linux. – jdweng Jan 09 '20 at 16:37