Oto przykładowy serializator dla System.Type, który serializuje nazwę Type jako ciąg BSON. Ma to pewne ograniczenia polegające na tym, że metoda Deserialize kończy się niepowodzeniem, jeśli nazwa typu nie jest typem systemu lub w tym samym zestawie, ale można dostosować ten przykładowy serializator, aby zamiast tego zapisać 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();
}
}
Sztuczka polega na tym, aby poprawnie ją zarejestrować. Musisz zarejestrować go zarówno dla System.Type, jak i System.RuntimeType, ale System.RuntimeType nie jest publiczny, więc nie możesz odwoływać się do niego w kodzie. Ale możesz się do tego dostać za pomocą Type.GetType. Oto kod do zarejestrowania serializatora:
var typeSerializer = new TypeSerializer();
BsonSerializer.RegisterSerializer(typeof(Type), typeSerializer);
BsonSerializer.RegisterSerializer(Type.GetType("System.RuntimeType"), typeSerializer);
Użyłem tej pętli testowej, aby sprawdzić, czy działa:
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);
}
gdzie C jest po prostu pustą klasą:
public static class C
{
}