Reputation: 14970
I have a C# class to create a message.
public class ExMessage
{
private UInt16 m_SendingId = 123;
private byte m_control_byte_1;
private enum destination_service : byte
{
serv_1 = 0x0,
serv_2 = 0x1
};
private byte m_pd;
private byte m_filler_bytes;
private byte[] m_payload;
public byte[] Payload
{
get
{
return m_payload;
}
}
/// <summary>
/// Constructor.
/// </summary>
public ExMessage(byte[] payload)
{
m_pd = 0x0;
m_control_byte_1 = 0xA5;
m_payload = payload;
m_filler_bytes = 0xF;
}
protected void WriteBody(Stream stream)
{
stream.WriteByte(m_control_byte_1);
stream.WriteByte(0x0);
stream.WriteWordLittleEndian(m_SendingId);
stream.WriteByte((byte)destination_service.serv_2);
stream.WriteByte((byte)m_pd); // payload details
stream.WriteByte((byte)m_payload.Length); //write the payload length
var count = 0;
while (count < m_payload.Length) //copy over the actual payload.
{
stream.WriteByte((byte)m_payload[count]);
count++;
}
var len = 48 - (5 + m_payload.Length);
count = 0;
while (count < len) //copy over spare bytes 0x3
{
stream.WriteByte(m_filler_bytes);
count++;
}
}
public byte[] ToBytes()
{
MemoryStream stream = new MemoryStream();
WriteBody(stream);
return stream.ToArray();
}
I create the message as follows
var Message = new ExMessage(Encoding.UTF8.GetBytes("HelloWorld"));
Now my usage scenario is as follows.
1) The protocol that I am using imposes a size restriction of 40 bytes on the payload. If the number of bytes in the payload that I am passing is greater than 40
bytes it should be split into two messages.
2) Is there a way for the constructor to return a list of ExMessage
objects based on the size of the byte array that I pass into it.
3) If not, what is the best way to handle this scenario
Upvotes: 1
Views: 620
Reputation: 117057
Here's how I would do it:
var size = 4;
var messages =
Encoding.UTF8.GetBytes("HelloWorld") //48 65 6C 6C 6F 57 6F 72 6C 64
.Select((b, i) => new { b, i }) // Enumerable of byte and index
.GroupBy(x => x.i / size, x => x.b) // group by index divide by block size
.Select(x => new ExMessage(x.ToArray())); // create messages
That gives me:
You would implement it like this:
public class ExMessage
{
private const int __size = 4;
public static ExMessage[] Create(byte[] payload)
{
return payload
.Select((b, i) => new { b, i })
.GroupBy(x => x.i / __size, x => x.b)
.Select(x => new ExMessage(x.ToArray()))
.ToArray();
}
/* rest of class */
}
You'd then call it like this:
var messages = ExMessage.Create(Encoding.UTF8.GetBytes("HelloWorld"));
Upvotes: 3
Reputation:
No.
I'd use a static function on ExMessage, something like this:
class ExMessage
{
...
public static List<ExMessage> CreateMessages(byte[] payload)
{
List<byte[]> chunks = ... split payload into 40byte chunks...
return chunks.Select(p => new ExMessage(p).ToList();
}
...
}
Upvotes: 1