如何在 MongoDB 中为不同的字段名称注册 ScalarDiscriminatorConvention?

rmu*_*unn 3 c# mongodb mongodb-csharp-2.0 mongodb-.net-driver

我正在编写 C# 代码来从现有 MongoDB 数据库中提取数据并将其放入各种 C# 类中。数据库的一部分是多态的:如果字段type是 A,则该文档中将存在一组特定字段。如果type是B,则将存在一组不同的字段。这是 的完美用例ScalarDiscriminatorConvention,所以我正在使用ScalarDiscriminatorConvention("type"). 但我不知道如何让 MongoDB 驱动程序使用该约定!

关于约定的 MongoDB 手册页让我认为这可行:

var pack = new ConventionPack();
pack.Add(new CamelCaseElementNameConvention());
pack.Add(new ScalarDiscriminatorConvention("type"));

ConventionRegistry.Register(
    "My Custom Conventions",
    pack,
    t => t.FullName.StartsWith("MyNamespace."));
Run Code Online (Sandbox Code Playgroud)

但这会失败,因为它不像其他约定那样ScalarDiscriminatorConvention从接口派生。IConvention它派生自IDiscriminatorConvention,这是它自己的接口,但不派生自IConvention。并ConventionPack.Add期望一个IConvention参数。

那么如何注册不同的鉴别器字段呢?我已经翻阅 MongoDB 手册至少一个小时了,但我很茫然。他们似乎没有在我能找到的任何地方记录它。

Rob*_*tam 5

鉴别器约定与类映射约定是分开的。我假设您的类 A 和 B 派生自一个公共基类:

public class BaseClass
{
    public int Id;
}

public class A : BaseClass
{
    public int FA;
}

public class B : BaseClass
{
    public int FB;
}
Run Code Online (Sandbox Code Playgroud)

我还假设您希望鉴别器字段名称为“type”而不是默认的“_t”。

您可以为基类注册一个鉴别器约定,如下所示:

BsonSerializer.RegisterDiscriminatorConvention(typeof(BaseClass), new ScalarDiscriminatorConvention("type"));
Run Code Online (Sandbox Code Playgroud)

您现在可以序列化和反序列化 BaseClass 值,“type”字段将包含“A”或“B”,具体取决于值的实际类型。

我使用以下代码来验证序列化形式并验证序列化形式是否可以反序列化:

BaseClass a = new A { Id = 1, FA = 1 };
var jsonA = a.ToJson();
var deserializedA = BsonSerializer.Deserialize<BaseClass>(jsonA);

BaseClass b = new B { Id = 2, FB = 2 };
var jsonB = b.ToJson();
var deserializedB = BsonSerializer.Deserialize<BaseClass>(jsonB);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢。在基类上调用“BsonSerializer.RegisterDiscriminatorConvention”正是我所需要的。现在我知道要查找什么,我可以在 API 文档中找到它,但在我之前查找的参考文档中却找不到它。你帮了我很多忙! (2认同)