Marc在stackoverflow上提到,在protobuf-net的v2中,可以使用ProtoInclude属性(或类似的方法)来序列化/反序列化类层次结构,而无需在基类中指定每个子类型.这是实现了吗?我们有一个可以在外部库中派生的插件接口,因此无法知道派生类型是什么.我们可以在类型之间保持唯一的编号,但我在网上找不到任何示例,缺少使用ProtoInclude属性,需要指定子类型.
如果我不知道子类型是什么,我将如何使用protobuf-net实现继承?
假设我有一个像这样的不可变值类型:
[Serializable]
[DataContract]
public struct MyValueType : ISerializable
{
private readonly int _x;
private readonly int _z;
public MyValueType(int x, int z)
: this()
{
_x = x;
_z = z;
}
// this constructor is used for deserialization
public MyValueType(SerializationInfo info, StreamingContext text)
: this()
{
_x = info.GetInt32("X");
_z = info.GetInt32("Z");
}
[DataMember(Order = 1)]
public int X
{
get { return _x; }
}
[DataMember(Order = 2)]
public int Z
{
get { return _z; }
} …Run Code Online (Sandbox Code Playgroud) 如何使用protobuf-net序列化这样的对象:
public class MyObject{
public string Key {get; set;}
public List<Object> Values {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用TypeModel序列化它时,protobuf-net会抛出一个错误,指出它不知道如何序列化System.Object.现在我知道Values只会包含基元(int,string,float,DateTime等).那么我如何让protobuf-net知道这个呢?
我在使用Protobuf.net的项目中遇到此异常:
InvalidOperationException "Unexpected sub-type: foo"
Run Code Online (Sandbox Code Playgroud)
我有一个我要发送的类,如下所示:
class message
{
list<bar> listOfBars;
}
Run Code Online (Sandbox Code Playgroud)
foo继承了bar,但是protobuf似乎对此产生了阻碍并产生了上面的异常.这有什么办法吗?我需要能够在列表中保存所有不同的bar子类型,因此更难以/不可能采用更多类型约束的解决方案.
Google protobuf是高效序列化对象的好协议,但它只支持树的序列化,而不支持图形(缺少完整的对象参考跟踪).
在.NET中实现谷歌的想法很少.(即protobuf-csharp-port,或protosharp),但最有趣的是protobuf-net.
Protobuf-net更好,因为它的体系结构适合.NET世界,并且有几个加载项(并不总是与原始protobuf兼容,但非常有用).
其中一个加载项是打开引用跟踪(AsReference选项)的可能性,它允许甚至在循环时序列化复杂的图形.
不必要的Protobuf-net v2处于测试版,AsReference选项不适用于现实世界的场景.(没有这个选项一切都运行良好,但没有Reference Tracikng protobuf-net无法序列化图形,不再是有吸引力的序列化程序).
它仍然有一些错误:
所以,我不能使用这个伟大的工具,我正在寻找替代序列化器:
.net serialization protocol-buffers datacontractserializer protobuf-net
当使用ProtoBuf-Net在紧凑框架和完整的.Net框架之间进行序列化/反序列化时,是否有人知道任何问题?我有一个名为LogData的类,我在紧凑框架3.5下序列化,传输到服务器(运行.Net framework 4.0),然后反序列化.有时它会起作用,有时它会引发上述错误,我还没有将其缩小到任何特定原因.我已经用不同的值做了很多测试,并且在发生错误时似乎找不到任何押韵或理由.我在下面包括我的课程(减去各种构造函数).我已多次查看任一侧的字节缓冲区,但尚未发现通过线路从一侧传输到另一侧的数据存在差异.
[ProtoContract]
public class LogData
{
[ProtoContract]
public enum LogSeverity
{
[ProtoEnum(Name = "Information", Value = 0)]
Information,
[ProtoEnum(Name = "Warning", Value = 1)]
Warning,
[ProtoEnum(Name = "Error", Value = 2)]
Error,
[ProtoEnum(Name = "Critical", Value = 3)]
Critical
}
[ProtoMember(1)]
public string UserID { get; set; }
[ProtoMember(2)]
public string ComputerName { get; set; }
[ProtoMember(3)]
public ExceptionProxy Exception { get; set; }
[ProtoMember(4)]
public LogData.LogSeverity Severity { get; set; }
[ProtoMember(5)]
public string Source { get; …Run Code Online (Sandbox Code Playgroud) c# serialization compact-framework protobuf-net deserialization
使用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 ,而不是标记每个属性.
可能吗?