用MongoDb存储System.Type [英] Storing System.Type with MongoDb

查看:52
本文介绍了用MongoDb存储System.Type的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我存储此类时:

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

SomeType属性像这样被序列化:

SomeType property gets serialized like this:

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

,随后的所有查询都会失败.

and every subsequent query fails.

我正在使用官方的C#驱动程序.如何获取它来存储实际类型? 谢谢.

I'm using the official C# driver. How do I get it to store the actual Type? Thanks.

推荐答案

下面是System.Type的示例序列化程序,它将Type的名称序列化为BSON字符串.这有一些限制,因为如果类型名称不是系统类型或在同一程序集中,则Deserialize方法将失败,但是您可以调整此示例序列化程序以改为编写AssemblyQualifiedName.

Here's a sample serializer for System.Type that serializes the name of the Type as a BSON string. This has some limitations in that the Deserialize method fails if the type name is not a system type or in the same assembly, but you could tweak this sample serializer to write the AssemblyQualifiedName instead.

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来获得它.这是注册序列化器的代码:

The trick is to get it registered properly. You need to register it for both System.Type and System.RuntimeType, but System.RuntimeType is not public so you can't refer to it in your code. But you can get at it using Type.GetType. Here's the code to register the serializer:

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

我使用此测试循环来验证它是否有效:

I used this test loop to verify that it worked:

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
{
}

这篇关于用MongoDb存储System.Type的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆