如何使用通用基类定义protobuf-net模型?

时间:2011-07-18 21:46:38

标签: .net protobuf-net

鉴于以下类型:

  [DataContract]
  public class EntityId
  {
    [DataMember(Order = 1)]
    public string IdAsString { get; set; }
    [DataMember(Order = 2), XmlIgnore]
    public Type Type { get; set; }

    #region XML hacks

    [XmlElement("Type"), Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public string AssemblyQualifiedTypeName
    {
      get { return ValueConverter.Default.Type2String(Type); }
      set { Type = ValueConverter.Default.String2Type(value); }
    }

    #endregion
  }

  [DataContract]
  public class EntityRelation
  {
    [DataMember(Order = 1)]
    public int Id { get; set; }
    [DataMember(Order = 2)]
    public string Path { get; set; }
  }

  [DataContract]
  public class Base<TId>
  {
    [DataMember(Order = 1)]
    public TId Id { get; set; }
    [DataMember(Order = 2)]
    public string Name { get; set; }
    [DataMember(Order = 3)]
    public EntityId ParentId { get; set; }
    [DataMember(Order = 4)]
    public int LastChanged { get; set; }
    [DataMember(Order = 5)]
    public string Description { get; set; }
    [DataMember(Order = 6)]
    public EntityRelation EntityRelation { get; set; }
  }

  [DataContract]
  public class FlowFolder : Base<int>
  {
  }

此模型定义:

  var m = RuntimeTypeModel.Default;
  m.AutoCompile = false;
  m.Add(typeof(Base<int>), true).AddSubType(1, typeof(FlowFolder));

这个用法:

var entity = GetFlowFolder();
var typeTag = GetTypeTag(entity);
Model.SerializeWithLengthPrefix(stream, entity, null, PrefixStyle.Base128, typeTag);

我得到了这个例外:

System.InvalidOperationException occurred
  Message=Duplicate field-number detected; 1 on: NC.DTO.Base`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
  Source=protobuf-net
  StackTrace:
       at ProtoBuf.Serializers.TypeSerializer..ctor(Type forType, Int32[] fieldNumbers, IProtoSerializer[] serializers, MethodInfo[] baseCtorCallbacks, Boolean isRootType, Boolean useConstructor, CallbackSet callbacks, Type constructType) in z:\Work\protobuf-net-v2\protobuf-net\Serializers\TypeSerializer.cs:line 43
  InnerException: 

使用以下堆栈跟踪:

protobuf-net.dll!ProtoBuf.Serializers.TypeSerializer.TypeSerializer(System.Type forType, int[] fieldNumbers, ProtoBuf.Serializers.IProtoSerializer[] serializers, System.Reflection.MethodInfo[] baseCtorCallbacks, bool isRootType, bool useConstructor, ProtoBuf.Meta.CallbackSet callbacks, System.Type constructType) Line 43   C#
protobuf-net.dll!ProtoBuf.Meta.MetaType.BuildSerializer() Line 283 + 0xe3 bytes C#
protobuf-net.dll!ProtoBuf.Meta.MetaType.Serializer.get() Line 209 + 0x11 bytes  C#
protobuf-net.dll!ProtoBuf.Meta.RuntimeTypeModel.Serialize(int key, object value, ProtoBuf.ProtoWriter dest) Line 357 + 0x51 bytes   C#
protobuf-net.dll!ProtoBuf.ProtoWriter.WriteObject(object value, int key, ProtoBuf.ProtoWriter writer, ProtoBuf.PrefixStyle style, int fieldNumber) Line 101 + 0x45 bytes    C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.SerializeWithLengthPrefix(System.IO.Stream dest, object value, System.Type type, ProtoBuf.PrefixStyle style, int fieldNumber, ProtoBuf.SerializationContext context) Line 467 + 0x24 bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.SerializeWithLengthPrefix(System.IO.Stream dest, object value, System.Type type, ProtoBuf.PrefixStyle style, int fieldNumber) Line 435 + 0x32 bytes    C#

我正在使用rev 424。

我做错了什么?

感谢。

修改

我什么都不懂。如果我将Base<T>设置为非泛型类型,它也不起作用。我必须在这里遗漏一些非常基本的东西。

EDIT2

调试代码显示基本类型属性的字段编号与派生类型的字段编号一起收集在同一列表中。由此我推断,继承的唯一方法是使用代理。至少在修订版424中。

1 个答案:

答案 0 :(得分:3)

.AddSubType(1, typeof(FlowFolder)); vs [DataMember(Order = 1)]

用于标识子类型的字段编号不得与同一类型的任何已定义字段冲突。只需使用不冲突的数字。冲突仅适用于类型 - 它不必在子类型中是唯一的;例如,.AddSubType(8, typeof(FlowFolder));会没问题,FlowFolder是否有“字段8”也无关紧要。

  

由此我推断,继承的唯一方法是使用代理。

我不知道接下来是怎么回事......?