11

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 を強制したいと考えています。

出来ますか?

4

1 に答える 1

9

はい、この機能は完全にサポートされています。実際、v1 での不適切な設計上の決定を認めざるを得ない場合、implicit-zero-defaults もその 1 つになりますが、下位互換性のために、この動作はデフォルトで保持されます。探しているのはです。RuntimeTypeModel.UseImplicitZeroDefaultsこれはtrueデフォルトです。

v1 の動作に依存するコードの動作を ( 経由でSerilaizer.*)変更しないようにするために、既定のモデルでこの機能を変更することはできないため、次のことを行う必要があります。

  1. 独自のモデル/シリアライザー インスタンスを定義する
  2. 使用する前に設定UseImplicitZeroDefaults = falseしてください
  3. シリアル化/逆シリアル化コードでは、このインスタンスを使用します。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));

将来的に考えられるもう 1 つのアプローチは、アセンブリ レベルの属性を許可することです。これは、特に「プリコンパイラ」を使用しているユーザー (たとえば、モバイル デバイスや WinRT をターゲットにしている) に役立ちます。

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

これは、そのアセンブリ内のすべての型に適用されます。ちょっとした考え。もう 1 つの明らかな利点は、従来のSerializer.*API を使用するコードで機能することです。

于 2012-09-06T08:58:43.613 に答える