Protobuf-net错误:不期望类型,也不能推断出合同:BlockHeader

时间:2012-07-19 16:09:48

标签: c# protobuf-net openstreetmap

尝试通过以下来自此线程以及其他来源的信息来正确运行openstreetmap pbf文件的反序列​​化:

Protobuf-net Deserialize Open Street Maps

我目前正在使用r480的protobug dll。我使用protogen从osm proto创建了csharp类文件,但当我在代码中点击这一点时,我试图从流中读入:

BlockHeader header;
using (var tmp = new LimitedStream(file, length))
{
    header = Serializer.Deserialize<BlockHeader>(tmp); // exception occurs here
}

抛出以下异常:

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
  at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 506
  at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type) in C:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 488
  at ProtoBuf.Serializer.Deserialize[T](Stream source) in C:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 69
  at OsmParserDemo.MainWindow.OsmParse() in C:\Users\crussell\Documents\Visual Studio 2010\Projects\OsmParseMadness\OsmParserDemo\MainWindow.xaml.cs:line 57
  at OsmParserDemo.MainWindow..ctor() in C:\Users\crussell\Documents\Visual Studio 2010\Projects\OsmParseMadness\OsmParserDemo\MainWindow.xaml.cs:line 28

因此,在将代码结构与protobuf-net示例的代码结构进行比较时,我得到的印象是,我可能会遗漏一些关于识别每个成员的内容。这是正确的,还是我在这个空间的出路?非常感谢任何帮助或提示!

编辑:这是生成的FileFormat.cs类的BlockHeader片段:

BlockHeader

2 个答案:

答案 0 :(得分:12)

添加代码文件后,一切都变得清晰了。您正在使用的库,基于堆栈跟踪,是protobuf-net;但是.cs文件与protobuf-net没有没有。嗯,很少。

你看,有(至少)2个c#/ .net protobuf实现,我认为你是在混合它们:

  • protobuf-csharp-port由Jon Skeet提供,是Java版本的直接端口,意思是:它遵循相同的设计原则和API。如果你同时使用C#和Java,那就太诱人了。
  • protobuf-net是我的,并且是一个从头到尾的实现,旨在成为惯用的.NET,这意味着:它可以代码优先于现有类型(基本上,像{{1} },XmlSerializer等等,但如果你想要
  • ,还支持.proto的用法

令人困惑的是,它们都具有一个名为“protogen”的代码生成工具。 AFAIK,这个命名巧合只是自然的收敛/巧合,而不是计划(好的或恶意的)。

从protobuf-csharp-port的protogen生成的c#文件将与protobuf-csharp-port库一起使用

从protobuf-net的protogen生成的c#文件将与protobuf-net库一起使用

这是protobuf-net生成的版本,包括DataContractSerializer

BlockHeader

结论:

使用protobuf-net原子,或使用protobuf-csharp-port库。没有混搭。

答案 1 :(得分:2)

运行此代码时出现此类错误:

public IEnumerable<T> Deserialize<T>(string path)
{
    using (var stream = File.Open(path, FileMode.Open, FileAccess.Read))
    {
        var item = Serializer.Deserialize<IEnumerable<T>>(stream);
        return item;
    }
}

当我将IEnumerable<T>更改为List<T>时,问题就消失了。我猜ProtoBuff对接口一无所知,你应该指定你想反序列化的非抽象/接口类型。

UPD:总结:您应该反序列化为序列化的类型对象。没有基础类型。