Does protobuf-net support ArraySegment (yet?)

I read Protobuf-net memcache provider fails in append / set ArraySegment , which says it might be supported at some point.

I also tried the test suggested in this question which indicates that version 2.0.0.668 does not support it.

Has anyone had any success using ArraySegments with protobuf-net, or have an idea for an efficient method to send a byte array over a wire.

those. I have an object like this:

[ProtoContract] 
class Foo
{
    [ProtoMember(1)]
    public byte[] Data { get; set; }
}

      

And I want to serialize another T object to a byte array, assign it to Data, and then serialize Foo to another byte []. (Sounds inefficient, but the Foo class must be type-agnostic, can it be generic?).

The key point is that I would prefer to minimize allocation / GC, so I want to minimize copying arrays or allocating new ones every time the data is serialized.

Here is some sample code that demonstrates what I am trying to achieve more efficiently:

public class DataSender<T>
{
    private ISerializer serializer; //Could be any kind of binary serializer 
    public void Send(T obj)
    {
        MemoryStream serializationBuffer = new MemoryStream(); // Inefficent allocation
        serializer.Serialize(serializationBuffer, obj);
        var sendable = new Foo(){ Data=serializationBuffer.ToArray() } // Inefficent copy
        Sender.Send(sendable);
     }
}

      

Any suggestions for replacing my Foo object and / or submit code would be very much appreciated.

+3


source to share


1 answer


It looks too complicated to me. I think your idea of ​​making a Foo

generic is pretty good, so you could:

[ProtoContract]
class Foo<T>
{
    [ProtoMember(1)]
    public T Data { get; set; }
}

      

And then you will create a new object with simple code like:

var foo = new Foo<Bar>() { Data = new Bar() { Data = "Some Data" } };

      

However, based on your additional comments, you cannot guarantee that the object is serializable or has proto attributes. For example, the bar class might look like this:

class Bar
{
    public string Data { get; set; }
}

      

In this case, you can use the class RuntimeTypeModel

to customize the serialization at runtime.

Here is an example of full serialization and deserialization using protobuf with dynamic runtime configuration for a data object:



using (var serializationBuffer = new MemoryStream())
{
    var foo = new Foo<Bar>() { Data = new Bar() { Data = "Some Data" } };

    RuntimeTypeModel.Default.Add(foo.Data.GetType(), false)
        .Add(foo.GetType().GetProperties().Select(p => p.Name).ToArray());

    Serializer.Serialize(serializationBuffer, foo);

    serializationBuffer.Seek(0, SeekOrigin.Begin);

    var deserialized = Serializer.Deserialize<Foo<Bar>>(serializationBuffer);
}

      

Thus, you can use any object as a data object, even if it has no serialization attributes. You will have performance , however, since reflection is used to discover properties of the type. However, you need to gain flexibility .

The correct way to send this object across the wire using WCF would be to set up custom WCF behavior using protobuf ProtoEndpointBehavior

and then WCF will automatically serialize and deserialize your Foo objects using protobuf. This means that the client will just make sure that it is using objects decorated with proto attributes and send them over the wire. WCF will take care of serialization / deserialization.

Here is a detailed example of how to consume WCF protobuf services:

http://www.drdobbs.com/windows/working-with-protobuf-wcf-services/240159282?pgno=1

The effectiveness of sending data over the wire depends on many factors. If you are sending LOBs over the wire, you can set up WCF TransferMode

to use Streaming and then read the data in byte array blocks on the other end.

However, efficiency is something you should measure, not assume .

+1


source







All Articles