【问题标题】:Serializing object graph using MongoDB Bson serializer使用 MongoDB Bson 序列化器序列化对象图
【发布时间】:2015-05-29 02:50:54
【问题描述】:

我一直在使用 MongoDB Bson 序列化程序,使用以下代码:

class Program
{
    public class myValue
    {
        public int Id = 0;
        public string Label = "";
    }

    public class myValueMap : Dictionary<string, myValue>
    {
    }

    public class myProdData
    {
        public myValueMap  Mapping { get; set; }

    }
    public class mySystemPosition
    {
        public string Text { get; set; }
        public myProdData ProdData { get; set; }

    }
    static void Main(string[] args)
    {
        BsonClassMap.RegisterClassMap<mySystemPosition>();
        BsonClassMap.RegisterClassMap<myProdData>();
        BsonClassMap.RegisterClassMap<myValueMap>();
        BsonClassMap.RegisterClassMap<myValue>();
        var o = new mySystemPosition()
                    {
                        ProdData = new myProdData()
                                       {
                                           Mapping = new myValueMap()
                                                        {
                                                            {"123", new myValue() {Id = 1, Label = "Item1"}},
                                                            {"345", new myValue() {Id = 2, Label = "Item2"}},
                                                        }
                                       }
                    };
        var bson = o.ToBson();

        var text = Encoding.ASCII.GetString(bson);
    }
}

但是我似乎无法将 myProdData.Mapping 序列化....

我是否需要以特殊方式配置 MongoDB Bson 序列化程序才能使其工作?

【问题讨论】:

    标签: serialization mongodb mongodb-.net-driver bson


    【解决方案1】:

    如果您不需要自定义序列化(documentation),则无需使用BsonClassMap.RegisterClassMap。 您的所有类都将根据默认规则进行 desiialzied。

    我还稍微改变了你的示例以使其正常工作(我已将 myValueMap 类替换为 Dictionary):

        public class myProdData
        {
            public  Dictionary<string, myValue> Mapping { get; set; }
        }
    
        static void Main(string[] args)
        {
            var o = new mySystemPosition()
            {
                ProdData = new myProdData()
                {
                    Mapping = new Dictionary<string, myValue>()
                    {
                        {"123", new myValue() {Id = 1, Label = "Item1"}},
                        {"345", new myValue() {Id = 2, Label = "Item2"}},
                    }
                }
            };
    
            var json = o.ToJson();
            Console.WriteLine(json);
            Console.ReadKey();
        }
    

    这是控制台输出(格式正确):

    {
        "Text":null,
        "ProdData":{
            "Mapping":{
                "123":{
                    "_id":1,
                    "Label":"Item1"
                },
                "345":{
                    "_id":2,
                    "Label":"Item2"
                }
            }
        }
    }
    

    您可以使用ToJson() 扩展方法测试您的序列化,以查看所有内容是否正确,然后根据需要使用ToBson()

    【讨论】:

      【解决方案2】:

      问题是 myValueMap 派生自 Dictionary。这会导致 AutoMap 方法无法处理的类。

      我建议您直接使用字典,就像 Andrew 在他的回复中所做的那样。

      【讨论】:

        【解决方案3】:

        幸运的是,myValueMap 是一个我无法轻易更改的对象,但事实证明,创建自己的(反)序列化器非常容易......

            public class myValueMapSerializer : IBsonSerializer
            {
                public object Deserialize(Bson.IO.BsonReader bsonReader, System.Type nominalType, System.Type actualType, IBsonSerializationOptions options)
                {
                    if (nominalType != typeof(myValueMap)) throw new ArgumentException("Cannot serialize anything but myValueMap");
                    var res = new myValueMap();
                    var ser = new DictionarySerializer<string, myValue>();
                    var dic = (Dictionary<string, myValue>)ser.Deserialize(bsonReader, typeof(Dictionary<string, myValue>), options);
        
                    foreach (var item in dic)
                    {
                        res.Add(item.Key, item.Value);
                    }
                    return res;
                }
        
                public object Deserialize(Bson.IO.BsonReader bsonReader, System.Type nominalType, IBsonSerializationOptions options)
                {
                    throw new Exception("Not implemented");
                }
        
                public bool GetDocumentId(object document, out object id, out IIdGenerator idGenerator)
                {
                    id = null;
                    idGenerator = null;
                    return false;
                }
        
                public void Serialize(Bson.IO.BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
                {
                    if (nominalType != typeof(myValueMap)) throw new ArgumentException("Cannot serialize anything but myValueMap");
        
                    var ser = new DictionarySerializer<string, myValue>();
                    ser.Serialize(bsonWriter, typeof(DictionarySerializer<string, myValue>), value, options);
                }
        
                public void SetDocumentId(object document, object id)
                {
                    return;
                }
            }
        

        【讨论】:

        • 这是一个很好的解决方案。不过,我会从 GetDocumentId 和 SetDocumentId 抛出 NotSupportedException 。除了根文档之外,它们不应该被调用,如果它们被调用,你可能宁愿找出它而不是默默地失败。
        猜你喜欢
        • 2011-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多