MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Discriminateurs de type de pilote MongoDB C # avec une classe générique héritant d'une classe de base non générique

Après quelques expérimentations, j'ai découvert que vous pouvez écrire vos propres conventions de discriminateur. Je ne comprends pas vraiment pourquoi, mais la convention de discriminateur par défaut semble utiliser la propriété Name de la classe de type, au lieu du FullName, ce qui la rend inutile pour les classes génériques.

J'ai fini par utiliser ce code à la place :

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;
    }
}

Et l'enregistrer avec

BsonSerializer.RegisterDiscriminatorConvention(typeof(MyGenericClass<>), new FooDiscriminatorConvention()); //is this needed?
BsonSerializer.RegisterDiscriminatorConvention(typeof(MyAbstractClass), new FooDiscriminatorConvention());

J'ai également dû rendre la classe de base non abstraite, pour éviter l'erreur "impossible de créer des instances de classes abstraites". Ce serait bien de pouvoir avoir une classe de base abstraite, mais comme la classe dérivée est générique, je ne peux pas utiliser BsonKnownTypes.