Считывание двоичных данных из UDP в модель

#c# #.net #.net-core

Вопрос:

В моем приложении я получаю двоичные данные через UDP, я написал двоичный считыватель, который идет поле за полем и считывает соответствующий тип и присваивает его модели вручную. Есть ли способ определить модель таким образом, чтобы указать какому-либо (де)сериализатору, где искать определенное поле, вместо того, чтобы назначать все?

Некоторые поля могут быть массивами — их размеры известны и фиксированы, но модель об этом не знает.

Пример (текущий код):

 byte Field1 = binaryReader.ReadByte();
sbyte Field2 = binaryReader.ReadSByte();
float[] Field3 = ...
//etc.
 

Желаемый код:

 public class Model
{
   [BinaryPosition(1)]
   public byte Field1 { get; set;}
   [BinaryPosition(2)]
   public sbyte Field2 { get; set; }
   [BinaryPosition(3)]
   public float[] Field3 { get; set; }
}
//...
var model = BinaryDeserializer.Deserialize<Model>(byteBuffer);
 

Ответ №1:

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

Начиная с самого простого, POCO struct , который работает, как подразумевает POCO, с простыми типами C ( byte , int , в основном unmanaged типы значений, нет string или что-то еще). В вашем примере это было бы:

 struct Model
{
    public byte Field1;
    public sbyte Field2;
}
 

Существует множество способов преобразования вашего byte[] массива в эту структуру в порядке эффективности (и версии .Net): MemoryMarshal.Cast , fixed указатели и Marshal.PtrToStructure .

Если вам требуются более сложные объекты, такие как строки, вам нужно использовать MarshalAs атрибут, чтобы объявить, как вы хотите упаковать строку, обычно в виде массива значений или менее обычно в виде указателя, а затем вам нужно использовать Marshal.PtrToStructure , чтобы маршаллер автоматически обрабатывал все дополнительные копии для вас. Очевидно, гораздо менее эффективно.

Комментарии:

1. У меня нет строк, но у меня есть массивы, я также обновил вопрос

2. Массивы хороши, если они являются массивами в стиле C, то есть с постоянным размером. Вы можете использовать fixed ключевое слово array для создания массивов значений на месте.