最简单的 protobuf-net 示例 3 需要帮助

发布于 2024-11-10 00:59:54 字数 2267 浏览 3 评论 0原文

鉴于:

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(当然,我必须使用代理)。

编辑

如果我在方法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

Given:

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

I am trying the following code:

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));
}

It fails with:

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: 

So, I uncomment the third line, but then I get:

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: 

Hence, the question is - how do I (de)serialize an object property containing a primitive boxed value type instance?

Note, that the same approach does work with a non primitive value type, like DateTime (of course, I had to use a surrogate).

EDIT

If I comment the primitivity check in method ProtoBuf.Meta.MetaType.MetaType, then the following code works correctly:

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; }
}

Of course, I would like to see it work without the need for IntSurrogate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文