【问题标题】:Deserialising polymorphic types with MongoDB C# Driver使用 MongoDB C# 驱动程序反序列化多态类型
【发布时间】:2013-09-09 15:55:42
【问题描述】:

假设,我有一个基类

public class Node{
    public ObjectId Id;
    public String nodeName;
    public ObjectId parentNode;
}

和 2 个派生类

public class PlotNode:Node{
    public ObjectId Id;
    public String plotDetail;
}

public class EndNode:Node{
    public ObjectId Id;
    public int resultCode;
}

所有3个类的几个对象都被序列化在数据库中。

我拥有的唯一数据是 ObjectId 的列表,关于这些 id 唯一知道的是它们肯定是 Node id,但在反序列化时不知道它们是 Node、PlotNode 还是 EndNode。

我正在使用它来反序列化:

var collection = db.GetCollection<Node>("nodes");
var query = Query<Node>.EQ(e => e.Id, id);
Node node = collection.FindOne(query);

最后我得到的是节点,而不是实际的 PlotNodes 或 EndNodes。

我如何知道它们是否是派生类型之一并取回该类型的对象?

【问题讨论】:

  • 我实现此目的的唯一方法是使用自定义序列化程序并在序列化期间将派生类型写入 BsonDocument。然后,当您反序列化时,您会构造相应派生类型的对象。
  • 这是我认为可以做到的方式之一,但我认为驱动程序本身会有一种内置方式。那我就这样吧,谢谢你的评论。
  • 如果您遇到困难,请告诉我。我在序列化时写了__t : { _type: '.net-type-string', _name: 'just the class name' }

标签: c# mongodb deserialization mongodb-.net-driver


【解决方案1】:

为什么你有相同的“public ObjectId Id;”在每个派生类中? 这不是一个好主意。它隐藏了父 ID 字段。

要解决您的问题,您需要“注册”您的派生类(就像在任何序列化/反序列化机制中一样)。 有3种方法可以做到:

  1. 声明方式 - 用以下方式装饰基 Node 类:

    [BsonKnownTypes(typeof(PlotNode), typeof(EndNode))]
    
  2. 通用方式 - 当类型在编译时已知时:

    BsonClassMap.RegisterClassMap<PlotNode>();
    BsonClassMap.RegisterClassMap<EndNode>();
    
  3. 动态方式 - 当编译时类型未知时:

    BsonClassMap.LookupClassMap(typeof(PlotNode));
    BsonClassMap.LookupClassMap(typeof(EndNode));
    

【讨论】:

  • 使用BsonClassMap.AddKnownType() 代替BsonClassMap.LookupClassMap() 会产生什么影响?
  • AddKnownType(type) 是 BsonClassMap 中的一个实例方法,这意味着您首先需要在调用该方法之前创建一个 BsonClassMap。更不用说,它还会注册已知类型(因此得名)。而 LookupClassMap(type) 是 BsonClassMap 上的静态方法,具有创建 BsonClassMap 实例、自动映射和注册它的副作用。
  • 只是为了好奇:你为什么建议使用 LINQ 而不是 QUERY?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多