Ecco un serializzatore di esempio per System.Type che serializza il nome del tipo come stringa BSON. Ciò presenta alcune limitazioni in quanto il metodo Deserialize non riesce se il nome del tipo non è un tipo di sistema o nello stesso assembly, ma è possibile modificare questo serializzatore di esempio per scrivere invece AssemblyQualifiedName.
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();
}
}
Il trucco è farlo registrare correttamente. Devi registrarlo sia per System.Type che per System.RuntimeType, ma System.RuntimeType non è pubblico, quindi non puoi fare riferimento ad esso nel tuo codice. Ma puoi ottenerlo usando Type.GetType. Ecco il codice per registrare il serializzatore:
var typeSerializer = new TypeSerializer();
BsonSerializer.RegisterSerializer(typeof(Type), typeSerializer);
BsonSerializer.RegisterSerializer(Type.GetType("System.RuntimeType"), typeSerializer);
Ho usato questo ciclo di test per verificare che funzionasse:
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);
}
dove C è solo una classe vuota:
public static class C
{
}