sql >> Base de Datos >  >> NoSQL >> MongoDB

Discriminadores de tipo de controlador MongoDB C# con clase genérica que hereda de una clase base no genérica

Después de experimentar un poco, descubrí que puedes escribir tus propias convenciones discriminatorias. Realmente no puedo entender por qué, pero la convención discriminadora predeterminada parece usar la propiedad Nombre de la clase de tipo, en lugar del Nombre completo, lo que la hace inútil para las clases genéricas.

Terminé usando este código en su lugar:

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

Y registrándolo con

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

También tuve que hacer que la clase base no fuera abstracta, para evitar el error "no se pueden crear instancias de clases abstractas". Sería bueno poder tener una clase base abstracta, pero dado que la clase derivada es genérica, no puedo usar BsonKnownTypes.