Вот пример сериализатора для System.Type, который сериализует имя типа в виде строки BSON. Это имеет некоторые ограничения в том, что метод Deserialize завершается ошибкой, если имя типа не является системным типом или в той же сборке, но вы можете настроить этот образец сериализатора, чтобы вместо него записать 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();
}
}
Хитрость заключается в том, чтобы правильно зарегистрировать его. Вам необходимо зарегистрировать его как для System.Type, так и для System.RuntimeType, но System.RuntimeType не является общедоступным, поэтому вы не можете ссылаться на него в своем коде. Но вы можете сделать это, используя Type.GetType. Вот код для регистрации сериализатора:
var typeSerializer = new TypeSerializer();
BsonSerializer.RegisterSerializer(typeof(Type), typeSerializer);
BsonSerializer.RegisterSerializer(Type.GetType("System.RuntimeType"), typeSerializer);
Я использовал этот тестовый цикл, чтобы убедиться, что он работает:
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);
}
где C - просто пустой класс:
public static class C
{
}