给定这些类:

public class Parent
{
    public IEnumerable<IChild> Children { get; set; }
}

public interface IChild { }

public class Child : IChild { }

将子属性作为数组插入,如下所示:
using MongoDB.Driver;
using System.Collections.Generic;

namespace TestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var db = new MongoClient().GetDatabase("Test");
            var collection = db.GetCollection<Parent>("Parent");
            collection.InsertOne(new Parent { Children = new[] { new Child() } });
        }
    }
}

数据库中缺少鉴别器:
{
    "_id":"5bf6aef6c0beccc414b70d45",
    "Child":[{}]
}

如果我使用列表:
collection.InsertOne(new Parent { Children = new List<IChild> { new Child() } });

鉴别器设置正确:
{
    "_id":"5bf6b074c0beccc414b70dc2",
    "Children":[{"_t":"Child"}]
}

这看起来像一个bug,或者至少是一个非常不直观的行为。
其他信息:
此行为是一个问题,因为缺少的鉴别器在反序列化对象时导致异常:
system.formatexception:“反序列化类testconsoleapp.parent的子属性时出错:无法确定要反序列化接口类型testconsoleapp.ichild的实际对象类型。”

最佳答案

导致此问题的原因是mongo没有发现ichild接口的实现类。换句话说,mongo驱动程序不知道必须使用子类创建ichild实现。这就是为什么它增加了鉴别器。
要解决此问题,可以指定隐含序列化。

public class Parent
{
[BsonSerializer(typeof(ImpliedImplementationInterfaceSerializer<IEnumerable<IChild>, IEnumerable<Child>>))]
    public IEnumerable<IChild> Children { get; set; }
}

使用此属性,它不会创建歧视,但将使用子类进行反序列化。
如果您想在动态实例上强制鉴别器,可以使用
[BsonDiscriminator(Required = true)]
    public class Child : IChild { }

请注意,应该将此头添加到需要强制创建鉴别器的所有类中。

09-26 01:51