2011-06-20 12 views
2
public class A 
    { 
    public int X { get; private set; } 
    public A(int x) 
    { 
     X = x; 
    } 

    public static implicit operator ASurrogate(A a) 
    { 
     return a == null ? null : new ASurrogate { X = a.X }; 
    } 
    public static implicit operator A(ASurrogate a) 
    { 
     return a == null ? null : new A(a.X); 
    } 
    } 

    [ProtoContract] 
    public abstract class ASurrogateBase 
    { 
    public abstract int X { get; set; } 
    } 

    [ProtoContract] 
    public class ASurrogate : ASurrogateBase 
    { 
    [OnSerializing] 
    public void OnSerializing(StreamingContext context) 
    { 
     X = 17; 
    } 

    [OnDeserialized] 
    public void OnDeserialized(StreamingContext context) 
    { 
     X = 117; 
    } 

    [ProtoMember(1)] 
    public override int X { get; set; } 
    } 

    [ProtoContract] 
    public class B 
    { 
    [ProtoMember(1)] 
    public A A { get; set; } 
    } 

    class Program 
    { 
    static void Main() 
    { 
     var m = RuntimeTypeModel.Default; 
     m.AutoCompile = false; 
     m.Add(typeof(ASurrogateBase), true).AddSubType(1, typeof(ASurrogate)); // (*) 
     m.Add(typeof(A), false).SetSurrogate(typeof(ASurrogate)); 

     var b = new B { A = new A(117) }; 
     using (var ms = new MemoryStream()) 
     { 
     Serializer.Serialize(ms, b); 
     ms.Position = 0; 
     var b2 = Serializer.Deserialize<B>(ms); 
     Debug.Assert(b.A.X == b2.A.X); 
     } 
    } 
    } 

このプログラムの問題は、どちらのシリアル化コールバックも呼び出されないことです。しかし、私がこのステートメント(*)を削除すると、すべてが機能します。protobuf-netのシリアル化コールバックとAddSubtypeの問題

これは仕様です。

答えて

1

これは仕様です。

いいえ、それはありません。短いバージョンは、サロゲートの継承を考慮していないということです。(さまざまな理由で)ほとんどのコールバックは、継承チェーンの実効基底型によってのみ呼び出されます(例外はOnDeserializingで、これはサブタイプレベルがオブジェクトとして作成されます)。

これはr414で修正されました