DDD场景下EF Core 7如何映射internal修饰的导航属性及实体
针对DDD聚合根内部实体EF Core映射的解决方案
1. 用友元程序集授权基础设施层访问
给域层项目添加InternalsVisibleTo特性,让基础设施层能访问域层的内部类型和成员,这样EF Core就能识别Bar类和它的属性,而应用服务层依然看不到Bar。
在域层的AssemblyInfo.cs或者项目文件里加:
[assembly: InternalsVisibleTo("你的基础设施层项目名称")]
如果是强命名程序集,还要加上公钥信息,确保只有指定的基础设施层能访问。
2. 域层内封装EF Core映射配置
把Bar的EF映射逻辑放在域层里,用internal类实现IEntityTypeConfiguration,基础设施层只需要加载这些配置,不用直接碰Bar。
示例代码(域层内):
internal class BarEntityConfig : IEntityTypeConfiguration<Bar> { public void Configure(EntityTypeBuilder<Bar> builder) { builder.ToTable("Bars"); builder.Property(b => b.SomeProperty).IsRequired(); // 其他字段、关联关系配置 } } internal class FooEntityConfig : IEntityTypeConfiguration<Foo> { public void Configure(EntityTypeBuilder<Foo> builder) { builder.ToTable("Foos"); builder.HasMany(f => f.Bars).WithOne(); } }
然后在基础设施层的DbContext里加载这些配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 自动加载域层里所有的IEntityTypeConfiguration实现 modelBuilder.ApplyConfigurationsFromAssembly(typeof(Foo).Assembly); }
这种方式最贴合DDD的封装思想——域模型自己掌控持久化规则,基础设施层只做执行,完全不用暴露Bar给外部。
3. 反射方式间接配置(无需修改域层权限)
如果不想给基础设施层开权限,也可以用反射拿到Bar的类型,再通过EF Core的API配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { var barType = typeof(Foo).Assembly.GetType("你的域层命名空间.Bar"); if (barType == null) return; // 配置Bar表和属性 var barEntity = modelBuilder.Entity(barType); barEntity.ToTable("Bars"); barEntity.Property("SomeProperty").IsRequired(); // 配置Foo和Bar的关联 modelBuilder.Entity<Foo>() .HasMany(nameof(Foo.Bars), barType) .WithOne(); }
这种写法不用改域层的任何权限,但代码可读性差,维护起来麻烦,适合极端注重封装的场景。
方案选择建议
- 优先选域层内封装配置:既保证封装性,代码又清晰,完全符合DDD的设计原则。
- 友元程序集:实现最简单,但要注意基础设施层是可信的,毕竟它能访问域层所有内部成员。
- 反射配置:迫不得已再用,比如不能修改域层的情况下。
内容的提问来源于stack exchange,提问作者nd92
相关产品推荐
相关产品推荐

