本文介绍了我可以使用 protobuf-net 序列化任意类型吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 protobuf-net 序列化一些对象,但不幸的是他们自由地使用 DateTimeOffset,protobuf-net 尚不支持.这导致了很多:

I'm trying to serialize some objects with protobuf-net, but unfortunately they make liberal use of DateTimeOffset, which is not yet supported by protobuf-net. This leads to lots of:

没有为类型定义序列化器:System.DateTimeOffset

我可以为未知类型定义自己的序列化例程吗?(同样的问题之前被问过,但他的问题已经解决了.)

Can I define my own serialization routine for unknown types? (The same question was asked earlier, but his problem was worked around.)

我使用的是最新的 protobuf-net beta,v2.0.0.431,在 .NET 4 下(如果重要的话).我也在使用运行时定义,所以我无法声明性地指定如何处理某些属性.

I'm using the latest protobuf-net beta, v2.0.0.431, under .NET 4 if it matters. I'm also using runtime definitions, so I have no way to declaratively specify how certain properties are to be handled.

推荐答案

有两种方法可以解决未知常见"类型的问题;第一种是使用 shim 属性,例如将值表示为类似内容的属性(例如 stringlong):

There are two ways of approaching the issue of unknown "common" types; the first is to use a shim property, for example a property that represents the value as something similar (a string or long for example):

[ProtoMember(8)]
public string Foo {
    get { ... read from the other member ... }
    set { ... assign the other member ... }
}

另一种方法是 surrogate,它是自动替换的第二个 protobuf 合约.使用代理的要求是:

The other approach is a surrogate, which is a second protobuf contract that is automatically substituted. The requirements to use a surrogate are:

  • 这两种类型(例如,DateTimeOffsetDateTimeOffsetSurrogate)之间必须有一个已定义的转换运算符(隐式或显式)
  • 然后使用SetSurrogate(surrogateType) 来训练protobuf-net,例如RuntimeTypeModel.Default.Add(typeof(DateTimeOffset), false).SetSurrogate(typeof(DateTimeOffsetSurrogate));
  • there must be a defined conversion operator (implicit or explict) between the two types (for example, DateTimeOffset and DateTimeOffsetSurrogate)
  • you then use SetSurrogate(surrogateType) to educate protobuf-net, for example RuntimeTypeModel.Default.Add(typeof(DateTimeOffset), false).SetSurrogate(typeof(DateTimeOffsetSurrogate));

shim 属性更简单,但需要每个成员重复.代理会自动应用于模型中该类型的所有实例.然后代理遵循标准的 protobuf-net 规则,因此您将指示要序列化的成员等.

the shim property is simpler, but requires repeat per-member. The surrogate is applied automatically to all instances of the type within the model. The surrogate then follows standard protobuf-net rules, so you would indicate which members to serialize, etc.

添加代码示例

using System;
using ProtoBuf;

[ProtoContract]
public class DateTimeOffsetSurrogate
{
    [ProtoMember(1)]
    public string DateTimeString { get; set; }

    public static implicit operator DateTimeOffsetSurrogate(DateTimeOffset value)
    {
        return new DateTimeOffsetSurrogate {DateTimeString = value.ToString("u")};
    }

    public static implicit operator DateTimeOffset(DateTimeOffsetSurrogate value)
    {
        return DateTimeOffset.Parse(value.DateTimeString);
    }
}

然后像这样注册

RuntimeTypeModel.Default.Add(typeof(DateTimeOffset), false).SetSurrogate(typeof(DateTimeOffsetSurrogate));

这篇关于我可以使用 protobuf-net 序列化任意类型吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 01:56