首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用MongoDb存储System.Type

用MongoDb存储System.Type
EN

Stack Overflow用户
提问于 2012-01-20 01:23:06
回答 2查看 1.2K关注 0票数 2

当我存储这个类时:

代码语言:javascript
复制
class MyClass{
    ...
    public Type SomeType {get;set;} 
    ...
}

SomeType属性按如下方式序列化:

代码语言:javascript
复制
"SomeType" : {
    "_t" : "RuntimeType"
}

随后的每一次查询都会失败。

我使用的是官方的C#驱动。如何让它存储实际的类型?谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-21 13:48:44

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

代码语言:javascript
复制
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来获得它。以下是注册序列化程序的代码:

代码语言:javascript
复制
var typeSerializer = new TypeSerializer();
BsonSerializer.RegisterSerializer(typeof(Type), typeSerializer);
BsonSerializer.RegisterSerializer(Type.GetType("System.RuntimeType"), typeSerializer);

我使用这个测试循环来验证它是否工作:

代码语言:javascript
复制
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只是一个空类:

代码语言:javascript
复制
public static class C
{
}
票数 7
EN

Stack Overflow用户

发布于 2012-01-20 01:48:41

不支持序列化System.Type (至少目前不支持)。相反,您必须将类型名称存储为字符串。

或者,您可以为System.Type编写一个序列化程序并注册它,但这可能比简单地将类型名存储为字符串要复杂得多。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8930443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档