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

Speichern von System.Type mit MongoDb

Hier ist ein Beispielserialisierer für System.Type, der den Namen des Typs als BSON-Zeichenfolge serialisiert. Dies hat einige Einschränkungen dahingehend, dass die Deserialize-Methode fehlschlägt, wenn der Typname kein Systemtyp ist oder sich in derselben Assembly befindet, aber Sie könnten diesen Beispielserialisierer so anpassen, dass er stattdessen AssemblyQualifiedName schreibt.

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

Der Trick besteht darin, es richtig zu registrieren. Sie müssen es sowohl für System.Type als auch für System.RuntimeType registrieren, aber System.RuntimeType ist nicht öffentlich, sodass Sie in Ihrem Code nicht darauf verweisen können. Aber Sie können es mit Type.GetType erreichen. Hier ist der Code zum Registrieren des Serialisierers:

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

Ich habe diese Testschleife verwendet, um zu überprüfen, ob es funktioniert hat:

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

wobei C nur eine leere Klasse ist:

public static class C
{
}