There is some legacy data that I have refactored to have a polymorphic structure:
class Shape {}
class Rectangle : Shape {}
class MyClass
{
public Shape shape;
}
BsonClassMap.RegisterClassMap<Shape>(cm =>
{
cm.AutoMap();
cm.SetIsRootClass(true);
cm.AddKnownType(typeof(Rectangle));
});
This works great for new data, the discriminator _t is created for shapes and rectangles accordingly. The problem I'm having is with legacy data which is all of type rectangle, but has no discriminator _t in the db since when it was created no polymorphism existed. When I try to read one of these objects, I get a deserialization error because it cannot map the legacy Rectangle to a Shape. I would prefer not to have to run a data migration to add the discriminator, is there a way for me to default the deserialization type to Rectangle if the discriminator is missing?
I figured this out, the solution is to implement a custom serializer to handle the deserialization, like this:
public class ShapeNullDiscriminatorSerializer : SerializerBase<Shape>
{
public override Shape Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.Null)
{
context.Reader.ReadNull();
return default(Shape);
}
var bsonDoc = BsonSerializer.Deserialize<BsonDocument>(context.Reader);
if (!bsonDoc.Contains("_t"))
return BsonSerializer.Deserialize<Rectangle>(bsonDoc);
return BsonSerializer.Deserialize<Shape>(bsonDoc);
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, FeedbackConfig value)
{
BsonSerializer.Serialize<Shape>(context.Writer, value, null, args);
}
}
And then map it like this on the parent class:
BsonClassMap.RegisterClassMap<MyClass>(cm =>
{
cm.AutoMap();
cm.MapMember(mc => mc.shape).SetSerializer(new ShapeNullDiscriminatorSerializer());
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With