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

Stockage de System.Type avec MongoDb

Voici un exemple de sérialiseur pour System.Type qui sérialise le nom du Type en tant que chaîne BSON. Cela a certaines limites dans la mesure où la méthode Deserialize échoue si le nom du type n'est pas un type système ou dans le même assembly, mais vous pouvez modifier cet exemple de sérialiseur pour écrire le AssemblyQualifiedName à la place.

public class TypeSerializer : IBsonSerializer
{
    public object Deserialize(BsonReader reader, Type nominalType, IBsonSerializationOptions options)
    {
        var actualType = nominalType;
        return Deserialize(reader, nominalType, actualType, options);
    }

    public object Deserialize(BsonReader reader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        if (reader.CurrentBsonType == BsonType.Null)
        {
            return null;
        }
        else
        {
            var fullName = reader.ReadString();
            return Type.GetType(fullName);
        }
    }

    public bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator)
    {
        throw new InvalidOperationException();
    }

    public void Serialize(BsonWriter writer, Type nominalType, object value, IBsonSerializationOptions options)
    {
        if (value == null)
        {
            writer.WriteNull();
        }
        else
        {
            writer.WriteString(((Type)value).FullName);
        }
    }

    public void SetDocumentId(object document, object id)
    {
        throw new InvalidOperationException();
    }
}

L'astuce consiste à l'enregistrer correctement. Vous devez l'enregistrer pour System.Type et System.RuntimeType, mais System.RuntimeType n'est pas public, vous ne pouvez donc pas y faire référence dans votre code. Mais vous pouvez y accéder en utilisant Type.GetType. Voici le code pour enregistrer le sérialiseur :

var typeSerializer = new TypeSerializer();
BsonSerializer.RegisterSerializer(typeof(Type), typeSerializer);
BsonSerializer.RegisterSerializer(Type.GetType("System.RuntimeType"), typeSerializer);

J'ai utilisé cette boucle de test pour vérifier que cela fonctionnait :

var types = new Type[] { typeof(int), typeof(string), typeof(Guid), typeof(C) };
foreach (var type in types)
{
    var json = type.ToJson();
    Console.WriteLine(json);
    var rehydratedType = BsonSerializer.Deserialize<Type>(json);
    Console.WriteLine("{0} -> {1}", type.FullName, rehydratedType.FullName);
}

où C est juste une classe vide :

public static class C
{
}