You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB C# Driver使用internal构造函数无法正常持久化DDD值对象

问题根因

MongoDB C# 2.13版本驱动默认的类序列化规则,会优先扫描类型的公共构造函数作为序列化/反序列化的入口,当没有公共构造函数时,默认不会触发属性的序列化逻辑,因此会将值对象序列化为空BSON文档。以下三个方案都可以在保留值对象internal构造函数的前提下解决问题:


方案1:使用[BsonConstructor]特性标记internal构造函数

直接在值对象的internal构造函数上添加[BsonConstructor]特性,驱动会通过反射调用该internal构造函数,同时正常扫描公共属性完成序列化。
注意:该方案会让领域层直接依赖MongoDB.Bson包,如果遵循DDD分层原则不希望领域层引入基础设施依赖,不推荐使用。
示例代码:

public class Information : Value<Information>
{
    public string Text { get; } 
    [BsonConstructor]
    internal Information(string text)
    {
        Text = text;
    }        
    // 其余代码保持不变
}

方案2:自定义Bson序列化器(推荐,符合DDD分层原则)

在基础设施层实现Information类的自定义序列化器,不需要修改领域层的任何代码,也不需要调整构造函数的访问权限,完全不破坏领域模型的封装性。

步骤1:实现自定义序列化器

public class InformationSerializer : SerializerBase<Information>
{
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Information value)
    {
        if (value == null)
        {
            context.Writer.WriteNull();
            return;
        }
        context.Writer.WriteString(value.Text);
    }

    public override Information Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonType = context.Reader.GetCurrentBsonType();
        if (bsonType == BsonType.Null)
        {
            context.Reader.ReadNull();
            return null;
        }
        var text = context.Reader.ReadString();
        // 直接调用领域层提供的公共工厂方法创建实例,天然符合领域校验规则
        return Information.CreateInformation(text);
    }
}

步骤2:全局注册序列化器

在应用启动阶段执行注册逻辑即可:

BsonSerializer.RegisterSerializer(new InformationSerializer());

方案3:配置程序集内部可见性

在领域层项目的程序集配置中添加可见性声明,允许MongoDB相关程序集访问领域层的internal成员,不需要修改现有业务代码。
如果项目存在AssemblyInfo.cs文件,直接添加以下配置:

[assembly: InternalsVisibleTo("MongoDB.Bson")]
[assembly: InternalsVisibleTo("MongoDB.Driver")]

如果是SDK风格的csproj项目,可以直接在csproj文件中添加:

<ItemGroup>
  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
    <_Parameter1>MongoDB.Bson</_Parameter1>
  </AssemblyAttribute>
  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
    <_Parameter1>MongoDB.Driver</_Parameter1>
  </AssemblyAttribute>
</ItemGroup>

注意:该方案会开放领域层所有internal成员的访问权限给MongoDB程序集,权限粒度较粗。


内容的提问来源于stack exchange,提问作者Cladoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 07:15:01