I'm writing C# code to pull data out of an existing MongoDB database and put it into various C# classes. One part of the database is polymorphic: if the field type
is A, then a certain set of fields will exist in that document. If type
is B, a different set of fields will exist. That's the perfect use case for ScalarDiscriminatorConvention
, so I'm using ScalarDiscriminatorConvention("type")
. But I don't know how to make the MongoDB driver use that convention!
The MongoDB manual page on conventions made me think that this would work:
var pack = new ConventionPack();
pack.Add(new CamelCaseElementNameConvention());
pack.Add(new ScalarDiscriminatorConvention("type"));
ConventionRegistry.Register(
"My Custom Conventions",
pack,
t => t.FullName.StartsWith("MyNamespace."));
But this fails because ScalarDiscriminatorConvention
doesn't derive from the IConvention
interface like the other conventions do. It derives from IDiscriminatorConvention
, which is its own interface that does not derive from IConvention
. And ConventionPack.Add
expects an IConvention
parameter.
So how do I register a different discriminator field? I've hunted through the MongoDB manual for at least an hour now and I'm quite at a loss. They don't seem to have it documented anywhere that I could find.
Discriminator conventions are separate from class mapping conventions. I'm assuming that your classes A and B derive from a common base class:
public class BaseClass
{
public int Id;
}
public class A : BaseClass
{
public int FA;
}
public class B : BaseClass
{
public int FB;
}
I'm also assuming that you want the discriminator field name to be "type" instead of the default of "_t".
You would register a discriminator convention for the base class like this:
BsonSerializer.RegisterDiscriminatorConvention(typeof(BaseClass), new ScalarDiscriminatorConvention("type"));
You can now serialize and deserialize BaseClass values and the "type" field will contain either "A" or "B" depending on the actual type of the value.
I used the following code to verify the serialized form and to verify that the serialized form could be deserialized:
BaseClass a = new A { Id = 1, FA = 1 };
var jsonA = a.ToJson();
var deserializedA = BsonSerializer.Deserialize<BaseClass>(jsonA);
BaseClass b = new B { Id = 2, FB = 2 };
var jsonB = b.ToJson();
var deserializedB = BsonSerializer.Deserialize<BaseClass>(jsonB);