MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB C#-Treibertyp-Diskriminatoren mit generischer Klasse, die von nicht generischer Basisklasse erbt

Nach einigem Experimentieren fand ich heraus, dass Sie Ihre eigenen Diskriminatorkonventionen schreiben können. Ich kann nicht wirklich verstehen, warum, aber die standardmäßige Unterscheidungskonvention scheint die Name-Eigenschaft der Typklasse anstelle des FullName zu verwenden, was sie für generische Klassen unbrauchbar macht.

Am Ende habe ich stattdessen diesen Code verwendet:

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

Und registrieren Sie es mit

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

Ich musste auch die Basisklasse nicht abstrakt machen, um den Fehler "Instanzen abstrakter Klassen können nicht erstellt werden" zu vermeiden. Es wäre schön, eine abstrakte Basisklasse zu haben, aber da die abgeleitete Klasse generisch ist, kann ich BsonKnownTypes nicht verwenden.