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);
}
}
}
The problem with this program is that neither serialization callback is invoked. If, however, I remove the statement (*), then everything works.
Is it by design?
No it isn’t. The short version is that it wasn’t considering inheritance of surrogates, and (for various reasons) most of the callbacks are only invoked by the effective base type of an inheritance chain (the exception here is OnDeserializing, which is invoked at sub-type levels as objects are created).
This is fixed in r414