c# - Protobuf-net 错误 : Type is not expected, 并且无法推断出任何合约:BlockHeader

标签 c# protobuf-net openstreetmap

通过遵循来自该线程以及其他来源的信息,尝试使 openstreetmap pbf 文件的反序列​​化正常工作:

Protobuf-net Deserialize Open Street Maps

我目前正在使用来自 r480 的 protobug dll。我使用 protogen 从 osm 原型(prototype)创建 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

最佳答案

添加代码文件后,一切都变得清晰起来。根据堆栈跟踪,您正在使用的库是 protobuf-net;但是那个 .cs 文件与 protobuf-net 没有任何关系。嗯,很少。

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

  • protobuf-csharp-port由 Jon Skeet 开发,是 Java 版本的直接端口,意思是:它遵循相同的设计原则和 API。如果您同时使用 C# 和 Java,这很有吸引力。
  • protobuf-net是我的,是一个从第一原则开始的实现,旨在成为惯用的 .NET,这意味着:它可以代码优先,针对您现有的类型(基本上,如 XmlSerializer DataContractSerializer 等可以),但如果需要,也支持从 .proto 中使用

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

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

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

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

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// Generated from: Foo.proto
namespace ConsoleApplication9
{
  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Blob")]
  public partial class Blob : global::ProtoBuf.IExtensible
  {
    public Blob() {}


    private byte[] _raw = null;
    [global::ProtoBuf.ProtoMember(1, IsRequired = false, Name=@"raw", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] raw
    {
      get { return _raw; }
      set { _raw = value; }
    }

    private int _raw_size = default(int);
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"raw_size", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    [global::System.ComponentModel.DefaultValue(default(int))]
    public int raw_size
    {
      get { return _raw_size; }
      set { _raw_size = value; }
    }

    private byte[] _zlib_data = null;
    [global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"zlib_data", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] zlib_data
    {
      get { return _zlib_data; }
      set { _zlib_data = value; }
    }

    private byte[] _lzma_data = null;
    [global::ProtoBuf.ProtoMember(4, IsRequired = false, Name=@"lzma_data", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] lzma_data
    {
      get { return _lzma_data; }
      set { _lzma_data = value; }
    }

    private byte[] _bzip2_data = null;
    [global::ProtoBuf.ProtoMember(5, IsRequired = false, Name=@"bzip2_data", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] bzip2_data
    {
      get { return _bzip2_data; }
      set { _bzip2_data = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }

  [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"BlockHeader")]
  public partial class BlockHeader : global::ProtoBuf.IExtensible
  {
    public BlockHeader() {}

    private string _type;
    [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"type", DataFormat = global::ProtoBuf.DataFormat.Default)]
    public string type
    {
      get { return _type; }
      set { _type = value; }
    }

    private byte[] _indexdata = null;
    [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"indexdata", DataFormat = global::ProtoBuf.DataFormat.Default)]
    [global::System.ComponentModel.DefaultValue(null)]
    public byte[] indexdata
    {
      get { return _indexdata; }
      set { _indexdata = value; }
    }
    private int _datasize;
    [global::ProtoBuf.ProtoMember(3, IsRequired = true, Name=@"datasize", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
    public int datasize
    {
      get { return _datasize; }
      set { _datasize = value; }
    }
    private global::ProtoBuf.IExtension extensionObject;
    global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
      { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
  }

}

结论:

要么使用 protobuf-net protogen,要么使用 protobuf-csharp-port 库。不得混搭。

关于c# - Protobuf-net 错误 : Type is not expected, 并且无法推断出任何合约:BlockHeader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11564914/

相关文章:

c# - 如何自动检测Arduino COM端口?

database-design - protobuf 消息或嵌套消息中最好有多个字段吗?

javascript - 为什么 map 上的圆圈大小会变化?

c# - 重新打开关闭的 NetworkStream?

c# - 在不锁定 GUI 的情况下暂停方法的执行。 C#

visual-studio - 在 Visual Studio/Rider 中使用 proto 文件中的导入

protobuf-net - 使用 protobuf-net 反序列化集合

firefox - 使用 OpenLayers 和自己的 OSM 服务器的 Firefox 中 map 图 block 不显示(全粉红色)

json - 使用 OpenStreetMap 获取特定国家/地区的所有城市

c# - 如何复制克隆 UIElement 并保留布局/渲染信息?