Na wat experimenteren kwam ik erachter dat je je eigen discriminatorconventies kunt schrijven. Ik begrijp niet echt waarom, maar de standaard discriminatorconventie lijkt de eigenschap Name van de typeklasse te gebruiken in plaats van de FullName, waardoor het nutteloos is voor generieke klassen.
Ik heb uiteindelijk deze code gebruikt:
class FooDiscriminatorConvention : IDiscriminatorConvention
{
public string ElementName
{
get { return "_t"; }
}
public Type GetActualType(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType)
{
if(nominalType!=typeof(MyAbstractClass))
throw new Exception("Cannot use FooDiscriminator for type " + nominalType);
var ret = nominalType;
var bookmark = bsonReader.GetBookmark();
bsonReader.ReadStartDocument();
if (bsonReader.FindElement(ElementName))
{
var value = bsonReader.ReadString();
ret = Type.GetType(value);
if(ret==null)
throw new Exception("Could not find type " + value);
if(!ret.IsSubclassOf(typeof(MyAbstractClass)))
throw new Exception("Database type does not inherit from MyAbstractClass.");
}
bsonReader.ReturnToBookmark(bookmark);
return ret;
}
public BsonValue GetDiscriminator(Type nominalType, Type actualType)
{
if (nominalType != typeof(MyAbstractClass))
throw new Exception("Cannot use FooDiscriminator for type " + nominalType);
return actualType.FullName;
}
}
En registreren met
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());
Ik moest ook de basisklasse niet-abstract maken om de fout "can not crete instances of abstract classes" te voorkomen. Het zou leuk zijn om een abstracte basisklasse te hebben, maar aangezien de afgeleide klasse generiek is, kan ik BsonKnownTypes niet gebruiken.