Протобуф-чистый минимум для кодирования строк и чисел - PullRequest
2 голосов
/ 08 апреля 2011

Я просмотрел как protobuf-net Марка Гравелла, так и Джона Скита, однако они, кажется, делают намного больше, чем я ищу, плюс у меня проблемы с запуском их кода (получение System & System.Xmlсправочные вопросы) но тогда я работаю с их последней на code.google.com.

Обычно я просматриваю их тесты, но в тестах Джона используется так много помощников, за которыми трудно следить, и Марк вывел OO и объектную зависимость на максимум.Если только я полностью не пропущу что-то, чем я мог бы быть.

Я ищу минимальные минимальные классы из того или другого проекта для кодирования строк или чисел (int, int16, in64, double, float, decimal и т. Д.).Я не хочу кодировать класс или вложенные классы.Я не ищу кого-то, чтобы написать все это тоже.Я надеюсь, что кто-то может либо указать мне на минимальные минимальные классы / методы, которые это делают, либо на фактические подробности о том, как реализовать это без особых усилий (кроме простого использования того, что реализовано Jon & Marc, или просто обратиться кGoogle Protocols Buffer docs).

В основном я ищу что-то простое, как:


public class test {

 public void serialize_test() {
  using(var ms = new MemoryStream())
  {
   var str = "This is a test!";
   Serializer.Serialize(ms, str);
   byte[] raw = ms.ToArray();
   ms.Position = 0;
   var obj = Serializer.Deserialize(ms);
   Assert.AreEqual(str, (string)obj);
  };
 }

 public void serialize_to_field_test() {
  using(var ms = new MemoryStream())
  {
   var str = "This is a test!";
   Serializer.SerializeField(ms, str, 1);
   Serializer.SerializeField(ms, "field 2 value", 2);
   Serializer.SerializeField(ms, "field 3 value", 3);
   Serializer.SerializeField(ms, 4, 4);
   byte[] raw = ms.ToArray();
   ms.Position = 0;
   // probably should use an iterator pattern
   var field1 = Serializer.DeserializeField(ms, 1);
   var field2 = Serializer.DeserializeField(ms, 2);
   var field3 = Serializer.DeserializeField(ms, 3);
   var field4 = Serializer.DeserializeField(ms, 4);
   Assert.AreEqual(str, (string)field1);
   Assert.AreEqual("field 2 value", (string)field2);
   Assert.AreEqual("field 3 value", (string)field3);
   Assert.AreEqual(4, (int)field4);
  };
 }
}

Ответы [ 2 ]

1 голос
/ 08 апреля 2011

Не совсем уверен, как протобуф подходит, так как вам не нужен сериализатор объектов, но:

  • BinaryWriter оборачивает поток и имеет инструменты для того, что вы хотите;формат не имеет ничего общего с protobuf, но должен работать.Обратите внимание, что для пар имя / значение вы просто пишете имя, а затем значение
  • , если вы действительно хотите, чтобы где-то здесь protobuf, protobuf-net v2 имеет ProtoWriter, что является базовым «я пишу значения», а необъекты;заметьте, однако, что он не обрабатывает имена полей, так как это не «вписывается» в спецификацию protobuf (которая использует числовые маркеры)

Очевидно, что для каждого есть двойники;BinaryReader и ProtoReader.

Лично я думаю, что вам будет удобнее мыслить в терминах объектов.Но вы можете сами управлять им, как я здесь .

Вот пример использования альфа-DLL:

using (var ms = new MemoryStream())
{
    var str = "This is a test!";
    using (var writer = new ProtoWriter(ms, null))
    {
        ProtoWriter.WriteFieldHeader(1, WireType.String, writer);
        ProtoWriter.WriteString(str, writer);
        ProtoWriter.WriteFieldHeader(2, WireType.String, writer);
        ProtoWriter.WriteString("field 2 value", writer);
        ProtoWriter.WriteFieldHeader(3, WireType.String, writer);
        ProtoWriter.WriteString("field 3 value", writer);
        // use Variant if never negative
        ProtoWriter.WriteFieldHeader(4, WireType.SignedVariant, writer);
        ProtoWriter.WriteInt32(4, writer);
    }
    byte[] raw = ms.ToArray();
    ms.Position = 0;
    string field1 = "", field2 = "", field3 = "";
    int field4 = 0;
    using (var writer = new ProtoReader(ms, null))
    {
        int field;
        while((field = writer.ReadFieldHeader()) > 0)
        {
            switch (field)
            {
                case 1: field1 = writer.ReadString(); break;
                case 2: field2 = writer.ReadString(); break;
                case 3: field3 = writer.ReadString(); break;
                case 4: // remove the Hint() if using Variant
                    writer.Hint(WireType.SignedVariant);
                    field4 = writer.ReadInt32(); break;
            }
        }
    }
    Console.WriteLine(field1);
    Console.WriteLine(field2);
    Console.WriteLine(field3);
    Console.WriteLine(field4);
}
1 голос
/ 08 апреля 2011

Если вы хотите сыграть свою собственную сериализацию, загляните в BitConverter .

Прежде чем я нашел такие вещи, как proto buf, это был базовый строительный блок, который я использовал для сериализации.У него есть методы для перехода к и из байтовых массивов для всех типов значений.Должно быть довольно легко обернуть это в класс, подобный вашему примеру кода.

Для строк вам нужно использовать кодировщик.

var encoding = new System.Text.UTF8Encoding ();var bytes = encoding.GetBytes (str);

...