我已阅读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对象和/或发送代码的建议。
答案 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,然后在另一端读取字节数组块中的数据。
然而,效率是你应该<强>衡量,而不是假设。