Как определить модель protobuf-net с базовым классом? - PullRequest
2 голосов
/ 19 июля 2011

С учетом этих типов:

  [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.

Что я делаю не так?

Спасибо.

EDIT

Я ничего не понимаю. Это не сработает, если я сделаю Base<T> также не универсальным типом. Я, должно быть, упускаю что-то действительно простое здесь.

EDIT2

Отладка кода показывает, что номера полей свойств базового типа собираются в одном списке с номерами полей производных типов. Из этого я делаю вывод, что единственный способ получения наследства - суррогаты. По крайней мере, в редакции 424.

1 Ответ

3 голосов
/ 19 июля 2011

.AddSubType(1, typeof(FlowFolder)); против [DataMember(Order = 1)]

Номер поля, используемый для идентификации подтипа, не должен конфликтовать с какими-либо определенными полями того же типа. Просто используйте число, которое не конфликтует . Конфликт относится только к этого типа - он не должен быть уникальным среди подтипов; например, .AddSubType(8, typeof(FlowFolder)); будет в порядке, и не имеет значения, имеет ли FlowFolder «поле 8».

Из этого я делаю вывод, что единственный способ получения наследства - это суррогаты.

Я не понимаю, как это следует ....?

...