Depois de algumas experiências, descobri que você pode escrever suas próprias convenções discriminadoras. Eu realmente não consigo entender o porquê, mas a convenção do discriminador padrão parece usar a propriedade Name da classe de tipo, em vez do FullName, o que a torna inútil para classes genéricas.
Acabei usando este código em vez disso:
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;
}
}
E registrando-o com
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());
Eu também tive que tornar a classe base não abstrata, para evitar o erro "não é possível criar instâncias de classes abstratas". Seria bom poder ter uma classe base abstrata, mas como a classe derivada é genérica, não posso usar BsonKnownTypes.