我有一个使用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来获取整个模型,而不是标记每个属性。
有可能吗?
答案 0 :(得分:9)
是的,完全支持此功能。实际上,如果我被迫承认v1中的错误设计决策,那么隐式零默认值将是其中之一 - 但为了向后兼容,默认情况下会保留该行为。您要查找的内容为RuntimeTypeModel.UseImplicitZeroDefaults
,默认为true
。
为避免更改依赖于v1行为的代码行为(通过Serilaizer.*
),无法在默认模型上更改此功能,那么你是什么需要做的是:
UseImplicitZeroDefaults = false
,之前使用Serializer.*
例如:
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的代码。