.net领域驱动设计的完整目录结构
.net领域驱动设计的完整目录结构(包含各种实体存放目录及外部实体存放目录)-完整版
一、解决方案级总览(补全版)
MySolution.sln
│
├── src/
│ ├── MyProject.Domain/ # 领域层(核心,零外部依赖)
│ ├── MyProject.Application/ # 应用层(用例编排)
│ ├── MyProject.Infrastructure/ # 基础设施层(技术实现)
│ ├── MyProject.Api/ # 接口层(HTTP 入口)
│ └── MyProject.SharedKernel/ # 共享内核(跨上下文共享基类)
│
├── tests/
│ ├── MyProject.Domain.Tests/ # 领域层单元测试
│ ├── MyProject.Application.Tests/ # 应用层单元测试
│ ├── MyProject.Infrastructure.Tests/ # 基础设施层单元测试
│ ├── MyProject.Api.Tests/ # API 层集成测试
│ └── MyProject.IntegrationTests/ # 端到端集成测试
│
├── docker/ # Docker 相关
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── docker-compose.override.yml
│
├── deploy/ # 部署配置
│ ├── k8s/ # Kubernetes 部署清单
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── configmap.yaml
│ └── helm/ # Helm Chart
│ └── ...
│
├── docs/ # 项目文档
│ ├── architecture/ # 架构文档
│ │ ├── C4-model.md
│ │ ├── bounded-contexts.md
│ │ └── decisions/ # 架构决策记录(ADR)
│ │ ├── 001-use-cqrs.md
│ │ └── 002-anti-corruption-layer.md
│ ├── api/ # API 文档
│ │ └── openapi.yaml
│ └── domain/ # 领域知识文档
│ ├── glossary.md # 通用语言词汇表
│ └── event-catalog.md # 领域事件目录
│
├── scripts/ # 构建/运维脚本
│ ├── build.ps1
│ ├── migrate-db.sh
│ └── seed-data.ps1
│
├── tools/ # 开发工具
│ └── code-generation/ # 代码生成模板
│ └── aggregate-template.t4
│
├── .editorconfig # 编辑器配置
├── .gitignore
├── Directory.Build.props # 全局 MSBuild 属性
├── Directory.Packages.props # 集中包版本管理
├── global.json # SDK 版本锁定
├── nuget.config # NuGet 源配置
└── README.md
二、领域层(Domain)— 完整版
MyProject.Domain/
│
├── Aggregates/ # 聚合根 + 聚合内部实体
│ ├── Order/
│ │ ├── Order.cs # 聚合根(充血模型)
│ │ ├── OrderItem.cs # 聚合内部实体
│ │ ├── OrderStatus.cs # 领域枚举(强类型)
│ │ └── OrderType.cs # 领域枚举
│ └── Customer/
│ ├── Customer.cs # 聚合根
│ ├── CustomerTier.cs # 值对象(嵌套在聚合内)
│ └── CustomerType.cs
│
├── Entities/ # 独立实体(不属于任何聚合)
│ ├── Product.cs
│ └── Warehouse.cs
│
├── ValueObjects/ # 值对象(不可变,按值判等)
│ ├── Money.cs # 金额(数值 + 币种)
│ ├── Address.cs # 地址
│ ├── DateRange.cs # 日期范围
│ ├── PhoneNumber.cs # 电话号码
│ ├── Email.cs # 邮箱(含格式校验)
│ ├── Percentage.cs # 百分比
│ └── Coordinates.cs # 地理坐标
│
├── Events/ # 领域事件
│ ├── IDomainEvent.cs # 领域事件基接口
│ ├── DomainEvent.cs # 领域事件抽象基类(含 EventId、OccurredOn)
│ ├── Order/
│ │ ├── OrderCreatedEvent.cs
│ │ ├── OrderConfirmedEvent.cs
│ │ ├── OrderPaidEvent.cs
│ │ ├── OrderCancelledEvent.cs
│ │ └── OrderShippedEvent.cs
│ └── Customer/
│ ├── CustomerRegisteredEvent.cs
│ └── CustomerTierUpgradedEvent.cs
│
├── Repositories/ # 仓储接口(仅契约)
│ ├── IOrderRepository.cs
│ ├── ICustomerRepository.cs
│ └── IReadOnlyRepository.cs # 只读仓储接口(CQRS 读侧)
│
├── Services/ # 领域服务(跨聚合的业务逻辑)
│ ├── PricingDomainService.cs
│ ├── InventoryDomainService.cs
│ └── DiscountPolicyService.cs
│
├── Specifications/ # 规约模式(复杂查询/校验条件封装)
│ ├── ISpecification.cs
│ ├── Specification.cs # 规约抽象基类
│ ├── Order/
│ │ ├── OrderIsPayableSpecification.cs
│ │ └── OrderBelongsToCustomerSpecification.cs
│ └── Customer/
│ └── CustomerIsActiveSpecification.cs
│
├── Factories/ # 工厂(复杂聚合的创建逻辑)
│ ├── IOrderFactory.cs # 工厂接口
│ └── OrderFactory.cs # 工厂实现
│
├── Policies/ # 业务策略/规则引擎
│ ├── IPricingPolicy.cs
│ ├── StandardPricingPolicy.cs
│ └── VipPricingPolicy.cs
│
├── StateMachines/ # 状态机(聚合状态流转规则)
│ ├── OrderStateMachine.cs
│ └── IStateMachine.cs
│
├── Exceptions/ # 领域异常
│ ├── DomainException.cs # 领域异常基类
│ ├── EntityNotFoundException.cs
│ ├── OrderDomainException.cs
│ ├── InsufficientStockException.cs
│ └── BusinessRuleViolationException.cs
│
└── ExternalContracts/ # ⭐ 外部实体契约(防腐层接口定义)
├── Payment/
│ ├── IPaymentGateway.cs # 防腐层接口
│ ├── PaymentResult.cs # 内部模型
│ └── PaymentMethod.cs # 内部枚举
├── Logistics/
│ ├── ILogisticsService.cs
│ ├── ShippingInfo.cs
│ └── ShippingStatus.cs
└── ThirdPartyProduct/
├── IExternalProductClient.cs
├── ExternalProductInfo.cs
└── ExternalProductCategory.cs
三、应用层(Application)— 完整版
MyProject.Application/
│
├── Common/ # 应用层公共组件
│ ├── Interfaces/
│ │ ├── ICurrentUserService.cs # 当前用户服务接口
│ │ ├── IDateTimeService.cs # 时间服务接口(方便测试)
│ │ └── IEmailService.cs # 邮件服务接口
│ ├── Models/
│ │ ├── Result.cs # 统一操作结果(成功/失败)
│ │ ├── Result{T}.cs # 泛型操作结果
│ │ └── PagedResult{T}.cs # 分页结果
│ └── Exceptions/
│ ├── ValidationException.cs
│ ├── ForbiddenAccessException.cs
│ └── NotFoundException.cs
│
├── Commands/ # CQRS — 命令(写操作)
│ ├── Orders/
│ │ ├── CreateOrder/
│ │ │ ├── CreateOrderCommand.cs
│ │ │ ├── CreateOrderCommandHandler.cs
│ │ │ ├── CreateOrderCommandValidator.cs
│ │ │ └── CreateOrderCommandResponse.cs
│ │ ├── CancelOrder/
│ │ │ ├── CancelOrderCommand.cs
│ │ │ ├── CancelOrderCommandHandler.cs
│ │ │ └── CancelOrderCommandValidator.cs
│ │ ├── ConfirmOrder/
│ │ │ └── ...
│ │ └── ShipOrder/
│ │ └── ...
│ └── Customers/
│ ├── RegisterCustomer/
│ │ └── ...
│ └── UpgradeCustomerTier/
│ └── ...
│
├── Queries/ # CQRS — 查询(读操作)
│ ├── Orders/
│ │ ├── GetOrderById/
│ │ │ ├── GetOrderByIdQuery.cs
│ │ │ ├── GetOrderByIdQueryHandler.cs
│ │ │ └── OrderDetailDto.cs # 查询返回的 DTO
│ │ ├── GetOrdersByCustomer/
│ │ │ ├── GetOrdersByCustomerQuery.cs
│ │ │ ├── GetOrdersByCustomerQueryHandler.cs
│ │ │ └── OrderSummaryDto.cs
│ │ └── SearchOrders/
│ │ ├── SearchOrdersQuery.cs
│ │ ├── SearchOrdersQueryHandler.cs
│ │ └── OrderSearchCriteria.cs
│ └── Customers/
│ └── ...
│
├── Services/ # 应用服务(非 CQRS 场景/复杂编排)
│ ├── OrderAppService.cs
│ └── CustomerAppService.cs
│
├── DTOs/ # 数据传输对象(层间传递)
│ ├── OrderDto.cs
│ ├── CustomerDto.cs
│ └── Enums/
│ └── OrderStatusDto.cs
│
├── EventHandlers/ # 领域事件处理器
│ ├── Order/
│ │ ├── OrderCreatedEventHandler.cs
│ │ ├── OrderPaidEventHandler.cs
│ │ └── OrderCancelledEventHandler.cs
│ └── Customer/
│ └── CustomerRegisteredEventHandler.cs
│
├── IntegrationEvents/ # ⭐ 集成事件(跨限界上下文通信)
│ ├── IIntegrationEvent.cs
│ ├── IntegrationEvent.cs # 集成事件基类
│ ├── Order/
│ │ ├── OrderPaidIntegrationEvent.cs
│ │ └── OrderShippedIntegrationEvent.cs
│ └── Customer/
│ └── CustomerTierChangedIntegrationEvent.cs
│
├── BackgroundJobs/ # ⭐ 后台任务/定时任务
│ ├── IBackgroundJob.cs
│ ├── OrderExpirationJob.cs # 超时未支付自动取消
│ ├── DailyReportJob.cs # 每日报表生成
│ └── DataSyncJob.cs # 数据同步任务
│
├── Behaviors/ # MediatR 管道行为
│ ├── LoggingBehavior.cs # 请求日志
│ ├── ValidationBehavior.cs # 自动校验
│ ├── TransactionBehavior.cs # 自动事务
│ ├── CachingBehavior.cs # 查询缓存
│ └── PerformanceBehavior.cs # 性能监控
│
├── Mappings/ # 对象映射配置
│ ├── OrderMappingProfile.cs
│ └── CustomerMappingProfile.cs
│
└── DependencyInjection/
└── ApplicationServiceExtensions.cs
四、基础设施层(Infrastructure)— 完整版
MyProject.Infrastructure/
│
├── Persistence/ # 持久化实现
│ ├── DbContexts/
│ │ ├── AppDbContext.cs # EF Core DbContext
│ │ └── IReadOnlyDbContext.cs # 只读 DbContext(CQRS 读侧,可连从库)
│ ├── Configurations/ # EF Core Fluent API 映射配置
│ │ ├── Order/
│ │ │ ├── OrderConfiguration.cs
│ │ │ └── OrderItemConfiguration.cs
│ │ └── Customer/
│ │ └── CustomerConfiguration.cs
│ ├── Repositories/ # 仓储实现
│ │ ├── OrderRepository.cs
│ │ ├── CustomerRepository.cs
│ │ └── Repository{T}.cs # 泛型仓储基类
│ ├── Migrations/ # EF Core 数据库迁移
│ │ ├── 20240101_InitialCreate.cs
│ │ └── AppDbContextModelSnapshot.cs
│ ├── PersistenceEntities/ # ⭐ 持久化实体(与领域模型严格分离)
│ │ ├── Order/
│ │ │ ├── OrderEntity.cs
│ │ │ └── OrderItemEntity.cs
│ │ └── Customer/
│ │ └── CustomerEntity.cs
│ ├── Converters/ # EF Core 值转换器
│ │ ├── MoneyValueConverter.cs # Money 值对象 ↔ 数据库列
│ │ ├── AddressValueConverter.cs
│ │ └── EnumValueConverter.cs
│ ├── Interceptors/ # EF Core 拦截器
│ │ ├── AuditableEntityInterceptor.cs # 自动填充 CreatedAt/UpdatedAt
│ │ ├── DispatchDomainEventsInterceptor.cs # 自动发布领域事件
│ │ └── SoftDeleteInterceptor.cs # 软删除拦截器
│ ├── Seeds/ # 种子数据
│ │ ├── DbInitializer.cs
│ │ └── SeedData/
│ │ └── initial-data.json
│ └── UnitOfWork.cs # 工作单元实现
│
├── ExternalServices/ # ⭐ 外部服务实现(防腐层实现)
│ ├── Payment/
│ │ ├── PaymentGateway.cs # 实现 IPaymentGateway
│ │ ├── PaymentGatewayClient.cs # HTTP 客户端(调用第三方支付 API)
│ │ ├── PaymentMapper.cs # 外部模型 → 内部模型
│ │ └── Dtos/ # 外部系统原始 DTO
│ │ ├── ExternalPaymentRequest.cs
│ │ └── ExternalPaymentResponse.cs
│ ├── Logistics/
│ │ ├── LogisticsService.cs
│ │ ├── LogisticsApiClient.cs
│ │ ├── LogisticsMapper.cs
│ │ └── Dtos/
│ │ └── ...
│ └── ThirdPartyProduct/
│ ├── ExternalProductClient.cs
│ ├── ExternalProductApiClient.cs
│ ├── ExternalProductMapper.cs
│ └── Dtos/
│ └── ...
│
├── Identity/ # ⭐ 身份认证与授权实现
│ ├── CurrentUserService.cs # 实现 ICurrentUserService
│ ├── JwtTokenGenerator.cs # JWT Token 生成
│ ├── PasswordHasher.cs # 密码哈希
│ └── Authorization/
│ ├── PermissionAuthorizationHandler.cs
│ └── ClaimsPrincipalExtensions.cs
│
├── Messaging/ # 消息队列 / 事件总线
│ ├── EventPublisher.cs # 领域事件发布器
│ ├── IntegrationEventPublisher.cs # 集成事件发布器
│ ├── RabbitMq/
│ │ ├── RabbitMqEventBus.cs
│ │ └── RabbitMqConsumer.cs
│ └── MassTransit/
│ ├── MassTransitConfig.cs
│ └── Consumers/
│ └── OrderPaidConsumer.cs
│
├── Caching/ # 缓存实现
│ ├── ICacheProvider.cs
│ ├── RedisCacheProvider.cs
│ ├── InMemoryCacheProvider.cs # 开发环境用
│ └── CacheKeys.cs # 缓存键常量
│
├── FileStorage/ # ⭐ 文件存储
│ ├── IFileStorageService.cs
│ ├── AzureBlobStorageService.cs
│ ├── MinioStorageService.cs
│ └── LocalFileStorageService.cs # 开发环境用
│
├── Logging/ # 日志实现
│ ├── SerilogConfig.cs
│ └── Enrichers/
│ └── UserEnricher.cs # 日志中自动附加用户信息
│
├── Monitoring/ # ⭐ 可观测性
│ ├── HealthChecks/
│ │ ├── DatabaseHealthCheck.cs
│ │ └── ExternalServiceHealthCheck.cs
│ ├── Metrics/
│ │ └── AppMetrics.cs # OpenTelemetry 指标
│ └── Tracing/
│ └── TracingConfig.cs # OpenTelemetry 链路追踪
│
├── Notifications/ # ⭐ 通知服务实现
│ ├── Email/
│ │ ├── IEmailSender.cs
│ │ ├── SmtpEmailSender.cs
│ │ ├── SendGridEmailSender.cs
│ │ └── Templates/
│ │ ├── OrderConfirmation.html
│ │ └── OrderShipped.html
│ └── Sms/
│ ├── ISmsSender.cs
│ └── AliyunSmsSender.cs
│
├── Config/ # 配置强类型
│ ├── DatabaseConfig.cs
│ ├── RedisConfig.cs
│ ├── JwtConfig.cs
│ ├── ExternalServiceConfig.cs
│ ├── PaymentGatewayConfig.cs
│ └── RabbitMqConfig.cs
│
└── DependencyInjection/ # 服务注册扩展
├── InfrastructureServiceExtensions.cs
├── PersistenceServiceExtensions.cs
├── ExternalServiceExtensions.cs
└── CachingServiceExtensions.cs
五、接口层(Api)— 完整版
MyProject.Api/
│
├── Controllers/ # API 控制器(极薄,仅转发给 MediatR)
│ ├── BaseController.cs # 控制器基类(提供 Mediator 快捷访问)
│ ├── OrdersController.cs
│ ├── CustomersController.cs
│ └── HealthController.cs # 健康检查端点
│
├── DTOs/ # API 层 DTO(请求/响应模型)
│ ├── Requests/
│ │ ├── CreateOrderRequest.cs
│ │ ├── UpdateOrderRequest.cs
│ │ ├── CancelOrderRequest.cs
│ │ └── OrderSearchRequest.cs
│ ├── Responses/
│ │ ├── OrderResponse.cs
│ │ ├── OrderDetailResponse.cs
│ │ ├── PagedResultResponse.cs
│ │ └── ErrorResponse.cs # 统一错误响应
│ └── Common/
│ ├── ApiResponse.cs # 统一响应包装 { code, message, data }
│ ├── ApiErrorResponse.cs # 详细错误响应(含校验错误明细)
│ └── ApiVersionResponse.cs
│
├── Middlewares/ # 自定义中间件
│ ├── ExceptionHandlingMiddleware.cs # 全局异常处理(领域异常 → HTTP 状态码)
│ ├── RequestLoggingMiddleware.cs # 请求/响应日志
│ ├── RequestTimingMiddleware.cs # 请求耗时统计
│ └── CorrelationIdMiddleware.cs # 链路追踪 CorrelationId 注入
│
├── Filters/ # Action 过滤器
│ ├── ValidationFilter.cs # 请求模型自动校验
│ ├── ModelBindingFilter.cs # 模型绑定错误处理
│ └── AuthorizationFilter.cs # 自定义授权过滤器
│
├── Extensions/ # 扩展方法(Program.cs 中注册)
│ ├── SwaggerExtensions.cs # Swagger/OpenAPI 配置
│ ├── AuthenticationExtensions.cs # JWT / OAuth 认证配置
│ ├── AuthorizationExtensions.cs # 授权策略配置
│ ├── CorsExtensions.cs # 跨域配置
│ ├── RateLimitingExtensions.cs # 限流配置
│ ├── CompressionExtensions.cs # 响应压缩
│ ├── HealthCheckExtensions.cs # 健康检查端点配置
│ └── ServiceCollectionExtensions.cs # 其他服务注册
│
├── Hubs/ # SignalR 实时通信(可选)
│ ├── NotificationHub.cs # 通知推送
│ └── OrderStatusHub.cs # 订单状态实时推送
│
├── Grpc/ # gRPC 服务端点(可选)
│ ├── Services/
│ │ └── OrderGrpcService.cs
│ └── Protos/
│ └── order.proto
│
├── Program.cs # 应用入口(服务注册 + 中间件管道)
├── appsettings.json # 通用配置
├── appsettings.Development.json # 开发环境配置
├── appsettings.Staging.json # 预发布环境配置
├── appsettings.Production.json # 生产环境配置
└── Properties/
└── launchSettings.json # 启动配置(端口、环境变量)
六、项目引用关系与依赖方向(总结)
MyProject.Api
├──→ MyProject.Application
│ ├──→ MyProject.Domain
│ └──→ MyProject.SharedKernel
└──→ MyProject.Infrastructure
├──→ MyProject.Application
├──→ MyProject.Domain
└──→ MyProject.SharedKernel
MyProject.Domain ← 零外部 NuGet 依赖(仅 System.*)
MyProject.SharedKernel ← 零业务层依赖,仅放跨上下文共享的基类
核心原则:
Domain层的.csproj中PackageReference必须为零,可用 CI 脚本扫描项目文件,发现任何PackageReference立即阻断构建。
七、各层 .csproj 依赖约束(总结)
| 项目 | 允许引用的 NuGet 包 | 禁止引用 |
|---|---|---|
Domain |
零(仅 System.*) |
EF Core、MediatR、FluentValidation 等一切外部包 |
SharedKernel |
极少(如 System.ComponentModel.Annotations) |
EF Core、任何框架包 |
Application |
MediatR、FluentValidation、AutoMapper | EF Core、Redis、RabbitMQ 客户端 |
Infrastructure |
EF Core、Redis、RabbitMQ、各种 SDK | 无限制(实现层) |
Api |
Swashbuckle、Serilog、SignalR | 无限制(入口层) |
八、外部实体(防腐层)数据流转示意(总结)
外部系统(如第三方支付)
│
▼
┌──────────────────────────────────────────────────┐
│ Infrastructure/ExternalServices/Payment │
│ │
│ PaymentGatewayClient ──调用──→ 外部 API │
│ │ │
│ ▼ │
│ ExternalPaymentResponse(外部原始模型,仅此处可见) │
│ │ │
│ ▼ PaymentMapper 转换 │
│ PaymentResult(内部模型,向上层暴露) │
└──────────────────────────────────────────────────┘
│ 实现接口
▼
┌──────────────────────────────────────────────────┐
│ Domain/ExternalContracts/Payment │
│ │
│ IPaymentGateway(接口定义) │
│ PaymentResult(内部值对象) │
└──────────────────────────────────────────────────┘
│ 被调用
▼
┌──────────────────────────────────────────────────┐
│ Application/Services │
│ │
│ OrderAppService 通过 IPaymentGateway │
│ 调用支付能力,只认识 PaymentResult │
└──────────────────────────────────────────────────┘
九、各层实体类型速查表(总结)
| 实体类型 | 存放目录 | 所属层 | 特征 |
|---|---|---|---|
| 聚合根 | Domain/Aggregates/{聚合名}/ |
领域层 | 有唯一 ID,充血模型,聚合唯一入口 |
| 聚合内部实体 | Domain/Aggregates/{聚合名}/ |
领域层 | 有唯一 ID,只能通过聚合根访问 |
| 独立实体 | Domain/Entities/ |
领域层 | 有唯一 ID,不属于特定聚合 |
| 值对象 | Domain/ValueObjects/ |
领域层 | 无 ID,不可变,按值判等 |
| 持久化实体 | Infrastructure/Persistence/PersistenceEntities/ |
基础设施层 | 含 ORM 映射特性,与领域模型严格分离 |
| 外部实体契约(接口) | Domain/ExternalContracts/ |
领域层 | 防腐层接口定义 |
| 外部实体(内部模型) | Domain/ExternalContracts/ |
领域层 | 转换后的内部表示 |
| 外部实体(实现) | Infrastructure/ExternalServices/ |
基础设施层 | 防腐层实现 + 外部 API 客户端 + 转换器 |
| API DTO | Api/DTOs/ |
接口层 | 请求/响应模型 |
| 应用 DTO | Application/DTOs/ |
应用层 | 层间数据传输对象 |
十、测试目录结构(补充)
tests/
├── MyProject.Domain.Tests/
│ ├── Aggregates/
│ │ ├── OrderTests.cs # 聚合根行为测试
│ │ └── CustomerTests.cs
│ ├── ValueObjects/
│ │ ├── MoneyTests.cs # 值对象运算测试
│ │ └── AddressTests.cs
│ ├── Services/
│ │ └── PricingDomainServiceTests.cs
│ └── Specifications/
│ └── OrderIsPayableSpecificationTests.cs
│
├── MyProject.Application.Tests/
│ ├── Commands/
│ │ ├── CreateOrderCommandHandlerTests.cs
│ │ └── CancelOrderCommandHandlerTests.cs
│ ├── Queries/
│ │ └── GetOrderByIdQueryHandlerTests.cs
│ └── EventHandlers/
│ └── OrderPaidEventHandlerTests.cs
│
├── MyProject.Infrastructure.Tests/
│ ├── Persistence/
│ │ ├── OrderRepositoryTests.cs # 仓储集成测试(用 Testcontainers)
│ │ └── Configurations/
│ │ └── OrderConfigurationTests.cs # EF Core 映射测试
│ └── ExternalServices/
│ ├── PaymentGatewayTests.cs # 防腐层测试(用 WireMock)
│ └── PaymentMapperTests.cs # 转换器单元测试
│
├── MyProject.Api.Tests/
│ ├── Controllers/
│ │ └── OrdersControllerTests.cs # 控制器集成测试(WebApplicationFactory)
│ └── Middlewares/
│ └── ExceptionHandlingMiddlewareTests.cs
│
└── MyProject.IntegrationTests/
├── Scenarios/ # 端到端场景测试
│ ├── OrderCreationScenarioTests.cs
│ └── OrderPaymentScenarioTests.cs
├── Fixtures/
│ ├── TestWebApplicationFactory.cs
│ └── DatabaseFixture.cs
└── Helpers/
└── TestDataBuilder.cs # 测试数据构造器
以上就是完整的 .NET DDD 目录结构,涵盖了从解决方案根目录到各层内部细节、测试、部署、文档等所有内容。需要我把某个具体聚合(比如 Order)的各层代码实际写出来吗?
---Q
”六、项目引用关系与依赖方向“是不是有问题?
你说得对,之前画的依赖关系图确实有问题。让我分析清楚:
原图的问题
MyProject.Api ← ❌ 问题在这里
├──→ MyProject.Application
│ └──→ MyProject.Domain
└──→ MyProject.Infrastructure ← ❌ Api 不应直接引用 Infrastructure
├──→ MyProject.Application
└──→ MyProject.Domain
核心错误:Api 直接引用了 Infrastructure,这违反了依赖倒置原则。Infrastructure 是实现细节,Api 层不应该知道它的存在。正确的做法是 Infrastructure 在运行时通过 DI 注入,Api 层只依赖抽象。
修正后的依赖关系
MyProject.Api
└──→ MyProject.Application
├──→ MyProject.Domain
└──→ MyProject.SharedKernel
MyProject.Infrastructure(运行时通过 DI 注入,非 Api 直接引用)
├──→ MyProject.Application (实现 Application 层定义的接口)
├──→ MyProject.Domain (实现 Domain 层定义的接口,如仓储、防腐层)
└──→ MyProject.SharedKernel
关键变化:
- Api 只引用 Application,不再直接引用 Infrastructure
- Infrastructure 作为实现层,在运行时由 DI 容器注入,对 Api 层透明
那 Program.cs 怎么注册 Infrastructure 的服务?
这是 .NET DI 框架的实际约束——组合根(Program.cs)必须知道实现类才能注册。有两种处理方式:
方式一:接受务实折中(大多数项目的做法)
Api 的 Program.cs 中调用 Infrastructure 的扩展方法注册服务:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddApplicationServices(); // Application 层注册
builder.Services.AddInfrastructureServices( // Infrastructure 层注册
builder.Configuration); // ← 这里需要引用 Infrastructure
这意味着 Api 项目实际上还是要引用 Infrastructure,但这是组合根的"特权"——组合根是整个应用中唯一允许知道所有实现细节的地方。
方式二:严格隔离(引入独立的组合根项目)
src/
├── MyProject.Domain/
├── MyProject.Application/
├── MyProject.Infrastructure/
├── MyProject.Api/ # 纯 API 层,不引用 Infrastructure
└── MyProject.Bootstrapper/ # ⭐ 独立的组合根/启动项目
MyProject.Bootstrapper(唯一的组合根)
├──→ MyProject.Api
├──→ MyProject.Application
├──→ MyProject.Infrastructure
└──→ MyProject.Domain
MyProject.Api
└──→ MyProject.Application # 严格只依赖 Application
Bootstrapper 是真正的启动入口,它引用所有项目并负责 DI 注册。Api 项目本身只引用 Application,保持纯净。
修正后的完整依赖约束表
| 项目 | 允许引用 | 禁止引用 |
|---|---|---|
Domain |
零(仅 System.*) |
一切外部包和内部项目 |
SharedKernel |
极少基础包 | Domain、Application、Infrastructure |
Application |
Domain、SharedKernel | Infrastructure、Api |
Infrastructure |
Application、Domain、SharedKernel | Api |
Api |
Application(严格模式)或 + Infrastructure(务实模式) | — |
总结: 之前的图把 Api → Infrastructure 画成了普通的项目依赖关系,没有区分"编译时引用"和"运行时注入",容易误导。严格来说 Api 不应直接依赖 Infrastructure,Infrastructure 应通过 DI 在运行时注入。
---Q
Infrastructure会实现Application定义的接口吗?
会的,但需要区分清楚哪些接口定义在 Application 层、哪些定义在 Domain 层,不能混为一谈。
Infrastructure 实现的接口来源有两个
1. 实现 Domain 层定义的接口(主要职责)
这是 Infrastructure 最核心的实现工作:
| Domain 层定义的接口 | Infrastructure 实现 |
|---|---|
IOrderRepository |
OrderRepository(EF Core) |
ICustomerRepository |
CustomerRepository(EF Core) |
IPaymentGateway(防腐层) |
PaymentGateway(HTTP 客户端) |
ILogisticsService(防腐层) |
LogisticsService(HTTP 客户端) |
IUnitOfWork |
UnitOfWork(DbContext 包装) |
2. 实现 Application 层定义的接口(技术基础设施)
Application 层在编排用例时,需要一些技术能力,但它不应该直接依赖具体实现,所以会定义接口:
| Application 层定义的接口 | Infrastructure 实现 |
|---|---|
ICurrentUserService |
CurrentUserService(从 HttpContext 提取用户信息) |
IDateTimeService |
DateTimeService(返回 DateTime.UtcNow) |
IEmailService |
SmtpEmailSender / SendGridEmailSender |
ICacheProvider |
RedisCacheProvider |
IIntegrationEventPublisher |
RabbitMqEventBus / MassTransitPublisher |
IFileStorageService |
AzureBlobStorageService |
这些接口的共同特征是:它们是技术基础设施能力,不是核心业务逻辑。Application 层需要发邮件、需要知道当前用户、需要缓存,但它不关心具体用什么技术实现。
为什么这样分?
Domain 层定义接口 → 与业务相关的契约(仓储、防腐层)
Application 层定义接口 → 与技术基础设施相关的契约(邮件、缓存、时间)
Infrastructure 层 → 统一实现以上所有接口
判断标准很简单:
- 如果这个接口涉及聚合的持久化或外部业务系统 → 定义在 Domain 层
- 如果这个接口涉及通用技术能力(发邮件、取时间、读写缓存) → 定义在 Application 层
修正后的依赖关系图
MyProject.Domain
└── 定义:IOrderRepository, IPaymentGateway, IUnitOfWork ...
MyProject.Application
├──→ MyProject.Domain
├── 定义:ICurrentUserService, IDateTimeService, IEmailService, ICacheProvider ...
└── 消费:通过接口调用,不关心实现
MyProject.Infrastructure
├──→ MyProject.Domain # 实现 Domain 层接口
├──→ MyProject.Application # 实现 Application 层接口
└── 实现:所有上述接口的具体技术实现
所以之前说的"Infrastructure 实现 Application 层定义的接口"是正确的,但主要实现对象还是 Domain 层的接口。Application 层的接口数量相对较少,都是通用技术能力。

浙公网安备 33010602011771号