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

Almacenamiento System.Type con MongoDb

Aquí hay un serializador de muestra para System.Type que serializa el nombre del Tipo como una cadena BSON. Esto tiene algunas limitaciones en el sentido de que el método Deserialize falla si el nombre del tipo no es un tipo de sistema o está en el mismo ensamblado, pero podría modificar este serializador de muestra para escribir el nombre ensamblado calificado en su lugar.

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

El truco es registrarlo correctamente. Debe registrarlo tanto para System.Type como para System.RuntimeType, pero System.RuntimeType no es público, por lo que no puede hacer referencia a él en su código. Pero puede obtenerlo usando Type.GetType. Aquí está el código para registrar el serializador:

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

Usé este ciclo de prueba para verificar que funcionó:

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

donde C es solo una clase vacía:

public static class C
{
}