Хранение System.Type с MongoDb - PullRequest
       5

Хранение System.Type с MongoDb

1 голос
/ 19 января 2012

Когда я сохраняю этот класс:

class MyClass{
    ...
    public Type SomeType {get;set;} 
    ...
}

Свойство SomeType сериализуется следующим образом:

"SomeType" : {
    "_t" : "RuntimeType"
}

и каждый последующий запрос не выполняется.

Я используюофициальный драйвер C #.Как мне получить его для хранения фактического типа?Спасибо.

Ответы [ 2 ]

7 голосов
/ 21 января 2012

Вот пример сериализатора для 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
{
}
2 голосов
/ 19 января 2012

Сериализация System.Type не поддерживается (по крайней мере, в настоящее время).Вместо этого вам придется хранить имя типа в виде строки.

В качестве альтернативы вы можете написать сериализатор для System.Type и зарегистрировать его, но это может быть более трудоемким, чем просто сохранение имени типа в виде строки.

...