protobuf-net是否支持ArraySegment(还?)

时间:2014-10-22 08:50:09

标签: c# serialization protobuf-net binary-serialization

我已阅读Protobuf-net memcache provider fails on append/set ArraySegment,表示可能会在某些时候支持它。

我也尝试过该问题中建议的测试,这表明版本2.0.0.668不支持它。

有没有人使用带有protobuf-net的ArraySegments成功,或者想知道通过网络发送字节数组的有效方法。

即。我有一个像这样的对象:

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

我想将一个不同的对象T序列化为一个字节数组,将其分配给Data,然后将Foo序列化为另一个byte []。 (听起来不尽如人意,但Foo类必须与该类型无关,它可能是通用的吗?)。

关键是我希望最小化分配/ GC,所以我希望每次序列化数据时最小化数组的复制或新的分配。

这是一些示例代码,它演示了我想要更有效地实现的目标:

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

非常欢迎任何有关替换我的Foo对象和/或发送代码的建议。

1 个答案:

答案 0 :(得分:1)

这看起来对我来说过于复杂。我认为你使Foo通用的想法非常好,所以你可以:

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

然后你将使用简单的代码实例化一个新的对象,如:

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

但是,根据您的附加注释,您不能保证对象是可序列化的,或者具有proto属性。例如,酒吧类看起来像:

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

在这种情况下,您可以使用RuntimeTypeModel类在运行时配置序列化。

以下是使用protobuf进行完整序列化和反序列化的示例,其中包含数据对象的动态运行时配置:

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

这样您就可以使用任何对象作为数据对象,即使它没有序列化属性也是如此。但是,由于使用反射来发现类型属性,因此会有性能惩罚。但是,您应该获得所需的灵活性

使用WCF通过线路发送此对象的正确方法是使用protobuf ProtoEndpointBehavior配置WCF自定义行为,然后WCF将使用protobuf自动序列化和反序列化您的Foo对象。这意味着客户端只会确保它使用用proto属性修饰的对象,并通过网络发送它们。 WCF将负责序列化/反序列化。

以下是如何使用WCF protobuf服务的综合示例:

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

通过线路发送数据的效率取决于许多因素。如果要通过线路发送大对象,可以将WCF TransferMode设置为使用Streaming,然后在另一端读取字节数组块中的数据。

然而,效率是你应该<强>衡量,而不是假设。