使用Protobuf-Net,我发现如果没有无参数构造函数或者我可能会遗漏某些东西,似乎不可能反序列化一个类?
我不想要一些带有无参数构造函数的类.我可以使用某种属性或其他技术吗?
在我们的客户端/服务器应用程序中,我们一直在使用BinaryFormatter进行序列化过程.出于性能原因,我们尝试迁移到protobuf-net(http://code.google.com/p/protobuf-net/).
我们的软件在客户端和服务器之间传输大量图表.
现在我正在寻找一种方法来确保使用protobuf序列化和反序列化的数据与通常由BinaryFormatter处理的数据完全相同.
逐位比较很简单:我使用BinaryFormatter序列化到文件.使用BinaryFormatter再次反序列化此文件.然后我使用ProtoBuf序列化到一个文件中.使用该文件中的ProtoBuf进行反序列化.使用BinaryFormatter再次序列化到文件中.
然后我可以简单地将该文件与原始文件进行比较.
但是,这两个文件不是100%相等.所以现在我需要找到一种方法来追踪差异.
是否有一些工具可以显示由BinaryFormatter序列化的数据?或者您是否知道其他帮助者进行深入比较并告诉我差异在哪里?
使用XMLSerializer并比较两个XML文件是不可能的,因为BinaryFormatter能够序列化比XMLSerializer更多的数据 - 即使没有明确标记字段.
谢谢,TH
我查了但似乎无法看到如何将类直接序列化为字节数组,然后使用Marc Gravell的protobuf-net实现从字节数组反序列化.
编辑:我改变了问题并提供了代码,因为原始问题如何序列化为byte []而不必通过流是无足轻重的.我很抱歉.
更新的问题:有没有办法不必处理泛型,而是在通过构造函数传递时通过反射推断属性"MessageBody"的类型?我假设我无法序列化对象类型,对吗?当前的解决方案看起来非常麻烦,因为每次实例化一个新消息时我都需要传递MessageBody的类型.有更简洁的解决方案吗?
我想出了以下内容:
class Program
{
static void Main(string[] args)
{
Message<string> msg = new Message<string>("Producer", "Consumer", "Test Message");
byte[] byteArray = msg.Serialize();
Message<string> message = Message<string>.Deserialize(byteArray);
Console.WriteLine("Output");
Console.WriteLine(message.From);
Console.WriteLine(message.To);
Console.WriteLine(message.MessageBody);
Console.ReadLine();
}
}
[ProtoContract]
public class Message<T>
{
[ProtoMember(1)]
public string From { get; private set; }
[ProtoMember(2)]
public string To { get; private set; }
[ProtoMember(3)]
public T MessageBody { get; private set; }
public Message()
{
}
public Message(string from, string to, T messageBody) …Run Code Online (Sandbox Code Playgroud) 我有一个使用protobuf-net序列化/反序列化的复杂模型,我们有几个错误,这个"功能"没有序列化默认值.
例:
[DataContract]
class Foo{
public Foo(){
// Value forced by constructor
this.Value = 1;
}
// Buggy, when Value is set to zero
[DataMember(Order = 1)]
public double Value {get; set}
}
Run Code Online (Sandbox Code Playgroud)
当Value = 0时,它不是由protobuf-net序列化的,但在反序列化期间,构造函数强制Value为1(并且protobuf-net不会改变它).
为了使它工作,我需要强制protobuf-net序列化值,用:
// Works fine
[DataMember(Order = 1, IsRequired = true)]
public double Value {get; set}
Run Code Online (Sandbox Code Playgroud)
但是,由于我们已经因为这个功能而出现了错误,我们希望为整个模型强制使用protobuf-net ,而不是标记每个属性.
可能吗?
我正在尝试ReadOnlyCollection使用protobuf-net 序列化和反序列化.但是,当protobuf-net尝试将List转换为ReadOnlyCollection时,反序列化时会抛出异常.
var roc = new ReadOnlyCollection<byte>(new byte[] {1, 2, 3});
var ms = new MemoryStream();
Serializer.Serialize(ms, roc);
ms.Position = 0;
var roc2 = Serializer.Deserialize<ReadOnlyCollection<byte>>(ms);
Console.WriteLine( BitConverter.ToString( roc2.ToArray() ) );
Run Code Online (Sandbox Code Playgroud)
有没有办法把它作为一个ReadOnlyCollection而不是序列化/反序列化List?在实际的应用程序中,它ReadOnlyCollection是我想要序列化的不可变对象的一部分,并且宁愿将它保留为ReadOnlyCollection.
尝试通过以下来自此线程以及其他来源的信息来正确运行openstreetmap pbf文件的反序列化:
我目前正在使用r480的protobug dll.我使用protogen从osm proto创建了csharp类文件,但是当我在代码中点击这一点时,我试图从流中读入:
BlockHeader header;
using (var tmp = new LimitedStream(file, length))
{
header = Serializer.Deserialize<BlockHeader>(tmp); // exception occurs here
}
Run Code Online (Sandbox Code Playgroud)
它抛出以下异常:
InnerException: System.InvalidOperationException
Message=Type is not expected, and no contract can be inferred: BlockHeader
Source=protobuf-net
StackTrace:
at ProtoBuf.Meta.TypeModel.ThrowUnexpectedType(Type type) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 1115
at ProtoBuf.Meta.TypeModel.TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, Int32 tag, Type type, Object& value, Boolean skipOtherFields, Boolean asListItem, Boolean autoCreate, Boolean insideList) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 848
at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 582 …Run Code Online (Sandbox Code Playgroud) 我在尝试使用protobuf-net序列化/反序列化复杂对象图时遇到了一些问题.
我正在研究遗留应用程序,我们正在使用.Net Remoting将GUI客户端连接到C#服务.由于使用默认值的对象图的序列化大小,我们看到海外用户的性能不佳BinaryFormatter,客户端和服务器之间的有限带宽(1Mbit/s)加剧了这种情况.
作为一个快速的胜利,我想我已经汇总了一个概念证明,通过实施,使用protobuf-net代替是否有任何性能提升ISerializable.在测试时,我遇到了一个问题,即没有维护对象引用.
我汇总了一个重新解决问题的例子.我期待Dictionary(Items [1])和对象BA中的对象与我AsReference=true在ProtoMember属性中指定的对象相同 .
使用protobuf-net 2.0.0.619,我看到反序列化时引发的异常(反序列化过程中引用跟踪对象更改了引用).
如果这不是支持的方案,请告诉我.
测试
[Test]
public void AreObjectReferencesSameAfterDeserialization()
{
A a = new A();
B b = new B();
b.A = a;
b.Items.Add(1, a);
Assert.AreSame(a, b.A);
Assert.AreSame(b.A, b.Items[1]);
B deserializedB;
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, b);
stream.Seek(0, SeekOrigin.Begin);
deserializedB = Serializer.Deserialize<B>(stream);
}
Assert.AreSame(deserializedB.A, deserializedB.Items[1]);
}
Run Code Online (Sandbox Code Playgroud)
类定义
[Serializable]
[ProtoContract]
public class A
{
}
[Serializable]
[ProtoContract]
public class B …Run Code Online (Sandbox Code Playgroud) 来到protobuf网,太棒了!我有一个关于空列表序列化的问题.
我首先声明要序列化的对象:
[ProtoContract]
class TestClass
{
[ProtoMember(1)]
List<int> _listOfInts = new List<int>();
public TestClass() { }
public List<int> ListOfInts
{
get { return _listOfInts; }
set { _listOfInts = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
如果_listOfInts为空(但不为null),当我deserialse时,此对象将始终为null.这对于protobuf约定是有意义的,我目前通过添加以下方法来解决这个问题:
[ProtoAfterDeserialization]
private void OnDeserialize()
{
if (_listOfInts == null)
_listOfInts = new List<int>();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我是否能够以更简洁的方式实现相同的功能,可能还有一个额外的attirbute,它会将null/empty对象初始化为空而不是null?
我对此完全感到困惑.我环顾四周,似乎找不到直接的答案.我有一个.proto文件,我的项目(全部是java)用来创建一些消息.
有一个重复的信息字段.这是我们创建的类型.当我使用protogen生成C#类时,此字段以只读方式显示,并且没有setter.
没有这个参数我无法完全构建消息.所以我的问题是.是否应该像这样生成重复字段,我应该以其他方式访问此只读列表?或者这是生成器中的错误?
生成的代码:
private readonly global::System.Collections.Generic.List<StringMapEntry> _factoryProperty = new global::System.Collections.Generic.List<StringMapEntry>();
[global::ProtoBuf.ProtoMember(2, Name=@"factoryProperty", DataFormat = global::ProtoBuf.DataFormat.Default)]
public global::System.Collections.Generic.List<StringMapEntry> factoryProperty
{
get { return _factoryProperty; }
}
Run Code Online (Sandbox Code Playgroud)
Proto文件部分:
repeated StringMapEntry factoryProperty = 2;
Run Code Online (Sandbox Code Playgroud)
我可能只是遗漏了一些非常明显的东西.谢谢你的帮助!
我注意到当我在多线程上下文中使用protobuf-net时,它会间歇性地失败并出现以下错误:
System.TimeoutException: Timeout while inspecting metadata; this may indicate a deadlock.
This can often be avoided by preparing necessary serializers during application initialization, rather than allowing multiple threads to perform the initial metadata inspection
Run Code Online (Sandbox Code Playgroud)
但是,如果我在第一次序列化特定类型时锁定对protobuf-net序列化程序的访问,则它可以正常工作.
protobuf-net意味着线程安全,还是这只是一个bug?