如何在 MongoDB.Bson 中序列化自定义集合?
MongoDB.Bson.Serialization 的文档似乎很薄弱。我不知道如何正确地将我的自定义集合放入 MongoDB 文档中。我正在使用他们的 默认 c# 驱动程序。
这是我试图序列化的类,但是当我在序列化然后反序列化后查看结果时,集合是空的。更具体地说,它创建了该类的一个新实例,但“_items”集合为空。鉴于这是私人室内收藏,我发现这很不寻常。该集合是一个更大的类的属性,其他类属性正在正确序列化。我已经使用内置序列化器将其序列化为 XML,效果很好。我认为这可能很简单,但缺少创建自定义序列化实现,我不知道它是什么。我需要做些什么来告诉序列化器将其视为集合吗?
由于我是 MongoDB 的新手,我还没有弄清楚如何转储大型原始文档来检查 MongoDB 文档本身是什么样子。这就是我现在正在做的事情。
[XmlRootAttribute(ElementName = "Children", IsNullable = true)]
public class ChildList : IList<SurveyItem>, ICollection<SurveyItem>
{
private SurveyItem _parent = null;
public ChildList(SurveyItem iParent)
{
_parent = iParent;
}
private List<SurveyItem> items = new List<SurveyItem>();
#region ICollection<SurveyItem> Members
public void Add(SurveyItem item)
{
//wire up the child.
item.Parent = _parent;
items.Add(item);
}
public void Clear()
{
items.Clear();
}
public bool Contains(SurveyItem item)
{
return items.Contains(item);
}
public void CopyTo(SurveyItem[] array, int arrayIndex)
{
items.CopyTo(array, arrayIndex);
}
public int Count
{
get { return items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(SurveyItem item)
{
item.Parent = null;
return items.Remove(item);
}
#endregion
#region IEnumerable<SurveyItem> Members
public IEnumerator<SurveyItem> GetEnumerator()
{
return items.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return (items as IEnumerable).GetEnumerator();
}
#endregion
#region IList<SurveyItem> Members
public int IndexOf(SurveyItem item)
{
return items.IndexOf(item);
}
public void Insert(int index, SurveyItem item)
{
item.Parent = _parent;
items.Insert(index, item);
}
public void RemoveAt(int index)
{
items[index].Parent = null;
items.RemoveAt(index);
}
public SurveyItem this[int index]
{
get
{
return items[index];
}
set
{
value.Parent = _parent;
items[index] = value;
}
}
#endregion
public SurveyItem[] ToArray()
{
SurveyItem[] output = new SurveyItem[items.Count];
for (int i = 0; i < items.Count; i++)
{
output[i] = items[i];
}
return output;
}
}
The documentation for the MongoDB.Bson.Serialization seems thin. I can't figure out how to get my custom collection into the MongoDB document correctly. I am using their default c# Driver.
This is the class that I am trying to serialize, but when I look at the result after it is it serialized and then deserialized, the collection is empty. More specifically, it creates a new instance of the class, but the "_items" collection was coming out null. I found this unusual given that it was a private interior collection. This collection is a property of a much larger class, the other class properties are serializing correctly. I have been serializing this to XML using the built-in serializers and this worked fine. I figure it's probably something simple, but short of creating a custom serialization implementation I don't know what it is. Is there something I have to do to tell the serializer to treat this as a collection?
Since I am am brand new to the MongoDB, I haven't figured out how to dump large raw documents to inspect what the MongoDB document itself looks like. That's what I am working on now.
[XmlRootAttribute(ElementName = "Children", IsNullable = true)]
public class ChildList : IList<SurveyItem>, ICollection<SurveyItem>
{
private SurveyItem _parent = null;
public ChildList(SurveyItem iParent)
{
_parent = iParent;
}
private List<SurveyItem> items = new List<SurveyItem>();
#region ICollection<SurveyItem> Members
public void Add(SurveyItem item)
{
//wire up the child.
item.Parent = _parent;
items.Add(item);
}
public void Clear()
{
items.Clear();
}
public bool Contains(SurveyItem item)
{
return items.Contains(item);
}
public void CopyTo(SurveyItem[] array, int arrayIndex)
{
items.CopyTo(array, arrayIndex);
}
public int Count
{
get { return items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(SurveyItem item)
{
item.Parent = null;
return items.Remove(item);
}
#endregion
#region IEnumerable<SurveyItem> Members
public IEnumerator<SurveyItem> GetEnumerator()
{
return items.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return (items as IEnumerable).GetEnumerator();
}
#endregion
#region IList<SurveyItem> Members
public int IndexOf(SurveyItem item)
{
return items.IndexOf(item);
}
public void Insert(int index, SurveyItem item)
{
item.Parent = _parent;
items.Insert(index, item);
}
public void RemoveAt(int index)
{
items[index].Parent = null;
items.RemoveAt(index);
}
public SurveyItem this[int index]
{
get
{
return items[index];
}
set
{
value.Parent = _parent;
items[index] = value;
}
}
#endregion
public SurveyItem[] ToArray()
{
SurveyItem[] output = new SurveyItem[items.Count];
for (int i = 0; i < items.Count; i++)
{
output[i] = items[i];
}
return output;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C# 驱动程序中的序列化程序只是查找并序列化类的公共读/写属性。序列化程序还具有 .NET 中标准集合类的特殊情况,例如字典。
您的集合元素存储在名为 items 的私有字段中。这就是为什么它们没有被序列化的原因。
您可以为您的类编写一个自定义序列化器。您可以实现 IBsonSerialized,也可以编写 IBsonSerializer 并将其注册到 BsonSerializer.RegisterSerializer。
您可能会遇到的一个问题是循环引用:您的集合具有对父级的引用,而父级很可能又具有对子级的引用。循环引用很难序列化。
The serializer in the C# driver simply looks for and serializes the public read/write properties of a class. The serializer also has special cases for standard collection classes in .NET like Dictionary.
Your collection elements are stored in a private field called items. That's why they don't get serialized.
You could write a custom serializer for your class. You can either implement IBsonSerializable, or you could write an IBsonSerializer and register it with BsonSerializer.RegisterSerializer.
One problem you will likely run into is circular references: your collection has a reference to a parent, which most likely in turn has a reference to the child. Circular references are hard to serialize.