Как создать переменную из подмассива - PullRequest
0 голосов
/ 22 декабря 2010

Итак, у меня есть гигантский байтовый массив, который представляет пакет данных.Существуют различные части пакета, такие как заголовок, тело сообщения, стоп-биты и т. Д. Как я могу создать переменные различных частей массива, чтобы при ссылке на переменную я редактировал подмассив?Я хотел бы использовать точечную запись, чтобы ссылка ByteArrayRepresentingPacket.Header фактически ссылалась на ByteArrayRepresentingPacket[0], ByteArrayRepresentingPacket.MessageBody на самом деле ссылалась бы ByteArrayRepresentingPacket[1] на ByteArrayRepresentingPacket[8] и т. Д. Структура кажется подходящей для этого, но как бы я перевелструктура в байтовый массив, когда мне нужно передать его?

Ответы [ 3 ]

3 голосов
/ 23 декабря 2010

Вам лучше не беспокоиться о том, чтобы заставить вашу структуру пакетов храниться в виде байтового массива. Стоимость процессора для преобразования в и из байтового массива, а также стоимость памяти для временного дублированного хранилища, скорее всего, незначительны. Создайте класс или набор классов для представления вашей структуры данных, а затем используйте BinaryWriter для преобразования его в байтовый массив в формате, требуемом вашим протоколом.

Если вы действительно хотите использовать структуру, изучите метод Marshal.StructureToPtr и атрибуты [LayoutKind] и [MarshalAs]. Но имейте в виду, что если ваша структура данных содержит поля переменной длины (строки или массивы), вы не сможете преобразовать ее в байтовый массив с помощью этого метода. И я не вижу причин, почему вы должны идти по этому пути. Он действительно предназначен для взаимодействия с Win32.

EDIT:

Еще одна мысль: если вы застряли с большим байтовым массивом и действительно хотите получить доступ к его фрагментам по имени, я бы создал реализацию IList<T>, которая взяла бы T[] смещение и длину просто использовал массив в качестве хранилища. Тогда вы можете создать класс так:

public class Packet
{
    public byte[] PacketData;
    public SubArray<byte> Header;
    public SubArray<byte> MessageBody;
    // Add more SubArrays for each of the remainder of your 8 packet pieces

    //modify this constructor as needed
    public Packet(byte[] data)
    {
        // replace the offsets and lengths here with appropriate data
        Header = new SubArray<byte>(data, 0, 10);
        MessageBody = new SubArray<byte>(data, 10, 100);
    }
}

public class SubArray<T> : IList<T>
{
    private T[] data;
    private int offset;
    private int length;

    public SubArray(T[] data, int offset, int length)
    {
         this.data = data;
         this.offset = offset;
         this.length = length;
    }

    public T this[int i]
    {
         get
         {
             if (i < 0 || i >= length) throw new ArgumentOutOfRangeException();
             return data[i + offset];
         }

         set
         {
             if (i < 0 || i >= length) throw new ArgumentOutOfRangeException();
             data[i + offset] = value;
         }
    }

    // TODO: Implement the rest of IList<T> accordingly
}
1 голос
/ 23 декабря 2010
public class Packet
{
    public byte[] Header;
    public byte[] MessageBody;
    // Add a single-dimensional byte array for each of the remainder of your 8 packet //pieces

    //modify this constructor as needed
    public Packet(byte[] header, byte[] messageBody[])
    {
        Header = header;
        MessageBody = messageBody;
    }

    public byte[][] ToArray()
    {
        byte[][] byteArray = new byte[8][];
        byteArray[0] = Header;
        byteArray[1] = MessageBody;
        // The rest of your 8 go here
        return byteArray;
    }
}
0 голосов
/ 23 декабря 2010

Так что я закончил со структурой (как я и надеялся). Вот реализация:

public struct Packet
{
    /// <summary>
    /// Constructor for initializing packet
    /// </summary>
    /// <param name="header"></param>
    /// <param name="message"></param>
    public Packet(byte[] header, byte[] message)
        : this()
    {
        this.Header = header;
        this.Message = message;
    }

    // Properties representing each part of the sub-packet parts (can be made private if needed)
    public IEnumerable<byte> Header { get; set; }
    public IEnumerable<byte> Message { get; set; }
    public IEnumerable<byte> StopBit { get { return new byte[1] { 0xFF }; } }

    /// <summary>
    /// Returns the byte representation of the whole packet
    /// </summary>
    public byte[] GetBytes
    {
        get { return Header.Concat(Message).Concat(StopBit).ToArray(); }
    }
}

Я сохранил все как IEnumerable, чтобы я мог просто использовать оператор .Concat LINQ (чтобы все было чисто и лаконично). В чем я не уверен, так это в том случае, если сбережение производительности, которое я получу от использования структуры (без упаковки / распаковки), будет отменено с помощью IEnumerable Properties и LINQ

...