c# - 无法为对象设置自定义鉴别器约定

标签 c# mongodb .net-core mongodb-.net-driver

我正在为 .NET Core 使用 MongoDB C# 驱动程序 (2.4.4)。 我想为所有对象注册自定义鉴别器约定:

BsonSerializer.RegisterDiscriminatorConvention(typeof(object), new CustomDiscriminatorConvention());

不幸的是,序列化程序没有调用我的自定义鉴别器约定。我检查了 BSON 序列化器源代码,看起来在这种情况下总是使用默认的层次鉴别器约定。

https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Bson/Serialization/BsonSerializer.cs (第 393-408 行):

// inherit the discriminator convention from the closest parent (that isn't object) that has one
// otherwise default to the standard hierarchical convention
Type parentType = type.GetTypeInfo().BaseType;
while (convention == null)
{
    if (parentType == typeof(object))
    {
        convention = StandardDiscriminatorConvention.Hierarchical;
        break;
    }
    if (__discriminatorConventions.TryGetValue(parentType, out convention))
    {
        break;
    }
    parentType = parentType.GetTypeInfo().BaseType;
}

如果循环中的两个 if 语句被颠倒,我的自定义约定将被找到并改为使用。为什么序列化程序不首先检查自定义对象鉴别器约定?

是否有另一种注册对象鉴别器约定的方法?还是覆盖默认约定?我需要编写自定义序列化程序吗?对于默认序列化程序首先应该支持的功能来说,这似乎有点矫枉过正。

请注意,这是一个库的一部分,在设计时我不知道哪些类类型将持久保存到数据库中。因此,我无法为更具体的类型注册约定。

最佳答案

我们正在使用的解决方法是注册一个普通约定,将鉴别器设置为我们希望的样子:

public class CustomDiscriminatorConvention : ConventionBase, IClassMapConvention
{
    public void Apply(BsonClassMap classMap)
    {
        Type type = classMap.ClassType;
        if (type.IsClass
            && type != typeof(string)
            && type != typeof(object)
            && !type.IsAbstract)
        {
            classMap.SetDiscriminator(GetCustomDiscriminatorFor(type));
        }
    }
}

要注册约定,请在您的应用启动时使用类似以下内容:

var conventions = new ConventionPack { new CustomDiscriminatorConvention(), ... };
ConventionRegistry.Register("Custom conventions", conventions, t => true);

关于c# - 无法为对象设置自定义鉴别器约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44748630/

相关文章:

c# - 如何将非日期值格式化为日期值

MongoDB 创建集合失败

编辑 mongo.conf 后 MongoDB 状态失败(代码退出,状态=2)

MongoDB 多键复合索引 - 需要帮助了解边界

c# - 减少.NET Core中常见列表属性比较的数量

c# - 如何将 ValueConverter 应用于基于约定的 Caliburn.Micro 绑定(bind)示例?

c# - 切开声音效果/静音的开始

c# - 为什么 DBContext 放入 IMemoryCache 后被释放(.NET Core/EF Core)

C# .net Core 数据库启用后重新连接Oracle

c# - 静态字段/属性初始化