强制protobuf-net序列化所有默认值

时间:2012-09-06 08:29:03

标签: c# serialization protobuf-net

我有一个使用protobuf-net序列化/反序列化的复杂模型,我们有几个错误,这个“功能”没有序列化默认值。

示例:

[DataContract]
class Foo{
  public Foo(){
    // Value forced by constructor
    this.Value = 1;
  }

  // Buggy, when Value is set to zero
  [DataMember(Order = 1)]
  public double Value {get; set}
}

当Value = 0时,它不是由protobuf-net序列化的,但是在反序列化期间,构造函数强制Value为1(并且protobuf-net不会改变它)。

为了使它工作,我需要强制protobuf-net序列化值,用:

  // Works fine
  [DataMember(Order = 1, IsRequired = true)]
  public double Value {get; set}

但是,由于我们已经因为这个功能而出现了错误,我们想强制使用protobuf-net来获取整个模型,而不是标记每个属性。

有可能吗?

1 个答案:

答案 0 :(得分:9)

是的,完全支持此功能。实际上,如果我被迫承认v1中的错误设计决策,那么隐式零默认值将是其中之一 - 但为了向后兼容,默认情况下会保留该行为。您要查找的内容为RuntimeTypeModel.UseImplicitZeroDefaults,默认为true

为避免更改依赖于v1行为的代码行为(通过Serilaizer.*),无法在默认模型上更改此功能,那么你是什么需要做的是:

  1. 定义您自己的模型/序列化程序实例
  2. 设置UseImplicitZeroDefaults = false之前使用
  3. 序列化/反序列化代码中的
  4. ,请使用此实例而不是Serializer.*
  5. 例如:

    private static readonly RuntimeTypeModel serializer;
    static MyType() { // your type-initializer for class MyType
        serializer = TypeModel.Create();
        serializer.UseImplicitZeroDefaults = false;
    }
    ... then when needed:
    serializer.Serialize(stream, obj);
    ...
    ObjType obj = (ObjType)serializer.Deserialize(stream, null, typeof(ObjType));
    

    我将来可能考虑的另一种方法是允许汇编级属性;这对于使用“预编译器”(例如,瞄准移动设备或WinRT)的人来说尤其有用 - 所以(只是大声思考):

    // this feature ***does not currently exist***
    [assembly:ProtoDefaults(UseImplicitZeroDefaults=false, SkipConstructor=true)]
    

    然后将应用于该程序集中的所有类型 。只是一个想法。另一个明显的优势是它可以使用经典Serializer.* API的代码。