Efter nogle eksperimenter fandt jeg ud af, at du kan skrive dine egne diskriminatorkonventioner. Jeg kan ikke rigtig forstå hvorfor, men standard diskriminatorkonventionen ser ud til at bruge Name-egenskaben for typeklassen i stedet for FullName, hvilket gør den ubrugelig for generiske klasser.
Jeg endte med at bruge denne kode i stedet:
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;
}
}
Og registrerer det med
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());
Jeg var også nødt til at gøre basisklassen ikke-abstrakt for at undgå fejlen "kan ikke skabe forekomster af abstrakte klasser". Det ville være rart at kunne have en abstrakt basisklasse, men da den afledte klasse er generisk, kan jeg ikke bruge BsonKnownTypes.