Нужна помощь в самом простом примере с protobuf-net 3 - PullRequest
3 голосов
/ 25 мая 2011

Дано:

public class E
{
  public object Y { get; set; }
}

Я пытаюсь следующий код:

var m = RuntimeTypeModel.Default;
m.Add(typeof(E), false).Add("Y");
// m.Add(typeof(object), false).AddSubType(1, typeof(int));

var e = new E { Y = 5 };
using (var ms = new MemoryStream())
{
  m.Serialize(ms, e);
  ms.Position = 0;
  var e2 = (E)m.Deserialize(ms, null, typeof(E));
  Debug.Assert(e.Y.Equals(e2.Y));
}

Не удается с:

System.InvalidOperationException occurred
  Message=No serializer defined for type: System.Object
  Source=protobuf-net
  StackTrace:
       at ProtoBuf.Meta.ValueMember.GetCoreSerializer(Type type, WireType& defaultWireType, Boolean asReference, Boolean dynamicType) in C:\Work\protobuf-net-v2\protobuf-net\Meta\ValueMember.cs:line 398
  InnerException: 

Итак, я раскомментирую третью строку, но затем получаю:

System.ArgumentException occurred
  Message=Not valid for primitive types
Parameter name: type
  Source=protobuf-net
  ParamName=type
  StackTrace:
       at ProtoBuf.Meta.MetaType..ctor(RuntimeTypeModel model, Type type) in C:\Work\protobuf-net-v2\protobuf-net\Meta\MetaType.cs:line 166
  InnerException: 

Следовательно, возникает вопрос - как (де) сериализовать свойство объекта, содержащее примитив экземпляр типа упакованного значения?

Обратите внимание, что тот же подход работает с не примитивным типом значения, таким как DateTime (конечно, я должен был использовать суррогат).

EDIT

Если я прокомментирую проверку примитивности в методе ProtoBuf.Meta.MetaType.MetaType, то следующий код будет работать правильно:

static void Main()
{
  var m = RuntimeTypeModel.Default;
  m.Add(typeof(E), false).Add("Y");
  m.Add(typeof(object), false).AddSubType(1, typeof(int));
  m.Add(typeof(IntSurrogate), false).Add("Value");
  m.Add(typeof(int), false).SetSurrogate(typeof(IntSurrogate));

  var e = new E { Y = 5 };
  using (var ms = new MemoryStream())
  {
    m.Serialize(ms, e);
    ms.Position = 0;
    var e2 = (E)m.Deserialize(ms, null, typeof(E));
    Debug.Assert(e.Y.Equals(e2.Y));
  }
}

internal class IntSurrogate
{
  public static implicit operator int(IntSurrogate surrogate)
  {
    return surrogate.Value;
  }
  public static implicit operator IntSurrogate(int v)
  {
    return new IntSurrogate { Value = v };
  }

  internal int Value { get; set; }
}

Конечно, я бы хотел, чтобы это работало без необходимости IntSurrogate.

...