Healnet.Core 核心模块
概述
Healnet.Core 是 Healnet 框架的核心模块,提供领域驱动设计(DDD)的基础设施,包括实体基类、仓储模式、领域服务、CQRS模式、事件驱动架构等核心组件。
核心特性
- ✅ 领域实体 - 提供实体基类和值对象支持
- ✅ 仓储模式 - 通用仓储接口和规范
- ✅ CQRS - 命令查询职责分离模式
- ✅ 领域事件 - 事件驱动架构支持
- ✅ 工作单元 - 事务管理抽象
- ✅ 依赖注入 - 服务注册扩展
- ✅ 异常处理 - 统一异常体系
- ✅ 验证机制 - 数据验证框架
核心组件
1. 实体与值对象
| 组件 |
说明 |
Entity<TKey> |
实体基类,包含主键和审计字段 |
AggregateRoot<TKey> |
聚合根基类,支持领域事件 |
ValueObject |
值对象基类,实现值相等性 |
Enumeration<T> |
枚举基类,支持强类型枚举 |
2. 仓储模式
| 接口 |
说明 |
IRepository<T, TKey> |
通用仓储接口 |
IReadOnlyRepository<T, TKey> |
只读仓储接口 |
ISpecification<T> |
规格模式接口 |
3. CQRS
| 组件 |
说明 |
ICommand<TResult> |
命令接口 |
ICommandHandler<TCommand, TResult> |
命令处理器接口 |
IQuery<TResult> |
查询接口 |
IQueryHandler<TQuery, TResult> |
查询处理器接口 |
IMediator |
中介者接口,协调命令和查询 |
4. 领域事件
| 组件 |
说明 |
IDomainEvent |
领域事件接口 |
IEventHandler<TEvent> |
事件处理器接口 |
IDomainEventDispatcher |
事件分发器 |
EventBus |
事件总线实现 |
5. 工作单元
| 接口 |
说明 |
IUnitOfWork |
工作单元接口 |
ITransaction |
事务接口 |
使用指南
1. 创建实体
// 基础实体
public class User : Entity<long>
{
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string PasswordHash { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
}
// 聚合根(支持领域事件)
public class Order : AggregateRoot<long>
{
public string OrderNo { get; set; } = string.Empty;
public long UserId { get; set; }
public decimal TotalAmount { get; set; }
public OrderStatus Status { get; set; } = OrderStatus.Pending;
public List<OrderItem> Items { get; set; } = new List<OrderItem>();
public void AddItem(Product product, int quantity, decimal price)
{
var item = new OrderItem(product.Id, quantity, price);
Items.Add(item);
TotalAmount += price * quantity;
// 添加领域事件
AddDomainEvent(new OrderItemAddedEvent(this, item));
}
public void Complete()
{
Status = OrderStatus.Completed;
AddDomainEvent(new OrderCompletedEvent(this));
}
}
// 值对象
public class Address : ValueObject
{
public string Street { get; private set; }
public string City { get; private set; }
public string Province { get; private set; }
public string ZipCode { get; private set; }
private Address() { }
public Address(string street, string city, string province, string zipCode)
{
Street = street;
City = city;
Province = province;
ZipCode = zipCode;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return City;
yield return Province;
yield return ZipCode;
}
}
// 强类型枚举
public class OrderStatus : Enumeration<OrderStatus>
{
public static readonly OrderStatus Pending = new(1, "Pending", "待处理");
public static readonly OrderStatus Paid = new(2, "Paid", "已支付");
public static readonly OrderStatus Completed = new(3, "Completed", "已完成");
public static readonly OrderStatus Cancelled = new(4, "Cancelled", "已取消");
public string Description { get; private set; }
private OrderStatus(int id, string name, string description) : base(id, name)
{
Description = description;
}
}
2. 创建仓储
public interface IOrderRepository : IRepository<Order, long>
{
Task<Order?> GetByOrderNoAsync(string orderNo);
Task<List<Order>> GetByUserIdAsync(long userId);
Task<List<Order>> GetOrdersByStatusAsync(OrderStatus status);
}
public class OrderRepository : RepositoryBase<Order, long>, IOrderRepository
{
public OrderRepository(IDbContext dbContext) : base(dbContext) { }
public async Task<Order?> GetByOrderNoAsync(string orderNo)
{
return await FindAsync(o => o.OrderNo == orderNo);
}
public async Task<List<Order>> GetByUserIdAsync(long userId)
{
return await FindAllAsync(o => o.UserId == userId);
}
public async Task<List<Order>> GetOrdersByStatusAsync(OrderStatus status)
{
return await FindAllAsync(o => o.Status == status);
}
}
3. 创建命令和查询
// 命令
public record CreateOrderCommand(
long UserId,
List<OrderItemDto> Items
) : ICommand<long>;
public class CreateOrderCommandHandler : ICommandHandler<CreateOrderCommand, long>
{
private readonly IOrderRepository _orderRepository;
private readonly IProductRepository _productRepository;
private readonly IUnitOfWork _unitOfWork;
public CreateOrderCommandHandler(IOrderRepository orderRepository,
IProductRepository productRepository,
IUnitOfWork unitOfWork)
{
_orderRepository = orderRepository;
_productRepository = productRepository;
_unitOfWork = unitOfWork;
}
public async Task<long> Handle(CreateOrderCommand command, CancellationToken cancellationToken)
{
// 验证产品库存
foreach (var item in command.Items)
{
var product = await _productRepository.GetByIdAsync(item.ProductId);
if (product == null || product.Stock < item.Quantity)
{
throw new BusinessException($"产品 {item.ProductId} 库存不足");
}
}
// 创建订单
var order = new Order
{
OrderNo = GenerateOrderNo(),
UserId = command.UserId
};
// 添加订单项
foreach (var item in command.Items)
{
var product = await _productRepository.GetByIdAsync(item.ProductId);
order.AddItem(product, item.Quantity, item.Price);
// 扣减库存
product.Stock -= item.Quantity;
await _productRepository.UpdateAsync(product);
}
// 保存订单
await _orderRepository.AddAsync(order);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return order.Id;
}
private string GenerateOrderNo()
{
return $"ORD{DateTime.Now:yyyyMMddHHmmss}{Guid.NewGuid():N[0..4]}";
}
}
// 查询
public record GetOrderQuery(long OrderId) : IQuery<OrderDto>;
public class GetOrderQueryHandler : IQueryHandler<GetOrderQuery, OrderDto>
{
private readonly IOrderRepository _orderRepository;
public GetOrderQueryHandler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
public async Task<OrderDto> Handle(GetOrderQuery query, CancellationToken cancellationToken)
{
var order = await _orderRepository.GetByIdAsync(query.OrderId);
if (order == null)
{
throw new NotFoundException("订单不存在");
}
return new OrderDto
{
Id = order.Id,
OrderNo = order.OrderNo,
UserId = order.UserId,
TotalAmount = order.TotalAmount,
Status = order.Status.Name,
Items = order.Items.Select(item => new OrderItemDto
{
ProductId = item.ProductId,
Quantity = item.Quantity,
Price = item.Price
}).ToList()
};
}
}
4. 使用中介者
public class OrderService
{
private readonly IMediator _mediator;
public OrderService(IMediator mediator)
{
_mediator = mediator;
}
public async Task<long> CreateOrderAsync(CreateOrderCommand command)
{
return await _mediator.Send(command);
}
public async Task<OrderDto> GetOrderAsync(long orderId)
{
return await _mediator.Send(new GetOrderQuery(orderId));
}
}
// Controller
[ApiController]
[Route("api/orders")]
public class OrderController : ControllerBase
{
private readonly IMediator _mediator;
public OrderController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
public async Task<IActionResult> CreateOrder([FromBody] CreateOrderCommand command)
{
var orderId = await _mediator.Send(command);
return CreatedAtAction(nameof(GetOrder), new { id = orderId }, null);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetOrder(long id)
{
var order = await _mediator.Send(new GetOrderQuery(id));
return Ok(order);
}
}
5. 领域事件处理
// 定义领域事件
public record OrderCompletedEvent(Order Order) : IDomainEvent;
// 事件处理器
public class OrderCompletedHandler : IEventHandler<OrderCompletedEvent>
{
private readonly IEmailService _emailService;
private readonly IInventoryService _inventoryService;
public OrderCompletedHandler(IEmailService emailService, IInventoryService inventoryService)
{
_emailService = emailService;
_inventoryService = inventoryService;
}
public async Task Handle(OrderCompletedEvent domainEvent, CancellationToken cancellationToken)
{
var order = domainEvent.Order;
// 发送订单完成邮件
await _emailService.SendOrderCompleteEmail(order.UserId, order.Id);
// 更新库存
await _inventoryService.UpdateInventory(order.Items);
// 记录审计日志
// await _auditService.LogOrderCompleted(order);
}
}
// 事件总线配置
public class EventBusModule
{
public static void RegisterEventHandlers(IServiceCollection services)
{
services.AddScoped<IEventHandler<OrderCompletedEvent>, OrderCompletedHandler>();
services.AddScoped<IEventHandler<OrderItemAddedEvent>, OrderItemAddedHandler>();
services.AddScoped<IEventHandler<UserRegisteredEvent>, UserRegisteredHandler>();
}
}
6. 规格模式
public class OrderByStatusSpecification : Specification<Order>
{
private readonly OrderStatus _status;
public OrderByStatusSpecification(OrderStatus status)
{
_status = status;
}
public override Expression<Func<Order, bool>> ToExpression()
{
return order => order.Status == _status;
}
}
public class OrdersWithItemsSpecification : Specification<Order>
{
public override Expression<Func<Order, bool>> ToExpression()
{
return order => order.Items.Any();
}
}
// 组合规格
public class ActiveOrdersSpecification : CompositeSpecification<Order>
{
public ActiveOrdersSpecification()
: base(new OrderByStatusSpecification(OrderStatus.Pending),
new OrdersWithItemsSpecification())
{
}
}
// 使用规格
public class OrderService
{
private readonly IOrderRepository _repository;
public OrderService(IOrderRepository repository)
{
_repository = repository;
}
public async Task<List<Order>> GetActiveOrdersAsync()
{
var spec = new ActiveOrdersSpecification();
return await _repository.FindAllAsync(spec);
}
}
7. 异常处理
// 自定义异常
public class BusinessException : Exception
{
public int ErrorCode { get; }
public BusinessException(string message) : base(message)
{
ErrorCode = 400;
}
public BusinessException(string message, int errorCode) : base(message)
{
ErrorCode = errorCode;
}
}
public class NotFoundException : BusinessException
{
public NotFoundException(string message) : base(message, 404) { }
}
public class UnauthorizedException : BusinessException
{
public UnauthorizedException(string message) : base(message, 401) { }
}
public class ForbiddenException : BusinessException
{
public ForbiddenException(string message) : base(message, 403) { }
}
// 全局异常处理中间件
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlerMiddleware> _logger;
public ExceptionHandlerMiddleware(RequestDelegate next, ILogger<ExceptionHandlerMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
_logger.LogError(exception, "An unhandled exception occurred.");
var response = new ApiResponse
{
Success = false,
Message = exception.Message
};
if (exception is BusinessException businessEx)
{
context.Response.StatusCode = businessEx.ErrorCode;
response.Code = businessEx.ErrorCode;
}
else
{
context.Response.StatusCode = 500;
response.Code = 500;
response.Message = "服务器内部错误";
}
context.Response.ContentType = "application/json";
await context.Response.WriteAsJsonAsync(response);
}
}
8. 数据验证
public class CreateOrderCommandValidator : AbstractValidator<CreateOrderCommand>
{
public CreateOrderCommandValidator()
{
RuleFor(x => x.UserId).NotEmpty().GreaterThan(0);
RuleFor(x => x.Items).NotEmpty();
RuleForEach(x => x.Items).ChildRules(items =>
{
items.RuleFor(item => item.ProductId).NotEmpty().GreaterThan(0);
items.RuleFor(item => item.Quantity).NotEmpty().GreaterThan(0);
items.RuleFor(item => item.Price).NotEmpty().GreaterThan(0);
});
}
}
// 验证管道行为
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
if (!_validators.Any())
{
return await next();
}
var context = new ValidationContext<TRequest>(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
服务注册
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 添加核心服务
builder.Services.AddCore();
// 添加 MediatR(CQRS)
builder.Services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssembly(typeof(CreateOrderCommand).Assembly);
cfg.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
});
// 添加验证服务
builder.Services.AddValidatorsFromAssembly(typeof(CreateOrderCommandValidator).Assembly);
var app = builder.Build();
// 注册全局异常处理中间件
app.UseMiddleware<ExceptionHandlerMiddleware>();
app.Run();
依赖包
<PackageReference Include="MediatR" Version="12.2.0" />
<PackageReference Include="FluentValidation" Version="11.9.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
架构说明
┌─────────────────────────────────────────────────────────────┐
│ Healnet.Core │
├─────────────────────────────────────────────────────────────┤
│ Domain Layer │
│ ├── Entities (Entity, AggregateRoot) │
│ ├── ValueObjects (ValueObject, Enumeration) │
│ ├── DomainEvents (IDomainEvent) │
│ └── Services (Domain Services) │
├─────────────────────────────────────────────────────────────┤
│ Application Layer │
│ ├── Commands (ICommand, ICommandHandler) │
│ ├── Queries (IQuery, IQueryHandler) │
│ ├── Validators (FluentValidation) │
│ └── Behaviors (Pipeline Behaviors) │
├─────────────────────────────────────────────────────────────┤
│ Infrastructure Layer │
│ ├── Repositories (IRepository, RepositoryBase) │
│ ├── UnitOfWork (IUnitOfWork) │
│ └── EventBus (IDomainEventDispatcher) │
└─────────────────────────────────────────────────────────────┘