开发者

protobuf-net bare minimum to encode strings and numbers

I've looked through both protobuf-net by Marc Gravell and Jon Skeet however they seem to do a lot more than what I'm looking for, plus I'm having issues running their code (getting System & System.Xml reference issues) but then I'm working from their latest on code.google.com.

Normally I would look through their tests but Jon's tests are using so many test helpers it gets hard to follow and Marc has taken OO and object dependency to the max. Unless I'm completely missing something, which I could be.

I'm looking for the bare minimum classes from one or the other project to encode strings or numbers (int,int16,in64,double,float,decimal,etc.). I do not want to开发者_运维技巧 encode a class or nested classes. I'm not looking for someone to write all this either. I'm hoping that someone can either point me to the bare minimum classes/methods that do this or to the actual details on how to implement this without a lot of effort (other than just using what Jon & Marc implemented or just refer to the Google Protocols Buffer docs).

Basically I'm looking for something as simple as:


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);
  };
 }
}


If you want to role your own serialization look into BitConverter.

Before I found things like proto buf this was the basic building block I used for serialization. It has methods to go to and from byte arrays for all value types. It should be fairly easy to wrap this into a class like your example code.

For strings you need to use an encoder.

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


Not entirely sure how protobuf fits in, since you don't want an object serializer, but:

  • BinaryWriter wraps a stream, and has tools for what you want; the format isn't anything to do with protobuf, but should work. Note that for name/value pairs you would just write the name then the value
  • it you really want protobuf in here somewhere, protobuf-net v2 has ProtoWriter which is basic "I write values", rather than objects; note, though, that it doesn't handle field-names, since that doesn't "fit" in the protobuf spec (which uses numeric markers)

Obviously there are twins for each; BinaryReader and ProtoReader.

Personally though, I think you'd find it more convenient to think in terms of objects. But you can take control of it yourself, like I did here.

Here's an example using the alpha 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);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜