Healnet.Core
2.0.0
See the version list below for details.
dotnet add package Healnet.Core --version 2.0.0
NuGet\Install-Package Healnet.Core -Version 2.0.0
<PackageReference Include="Healnet.Core" Version="2.0.0" />
<PackageVersion Include="Healnet.Core" Version="2.0.0" />
<PackageReference Include="Healnet.Core" />
paket add Healnet.Core --version 2.0.0
#r "nuget: Healnet.Core, 2.0.0"
#:package Healnet.Core@2.0.0
#addin nuget:?package=Healnet.Core&version=2.0.0
#tool nuget:?package=Healnet.Core&version=2.0.0
Healnet.Core 核心模块
版本: v1.5.0 | TFM: net10.0 | 依赖: Healnet.Common | NuGet: Healnet.Core 1.5.0
概述
Healnet.Core 是 Healnet 微服务框架的核心业务层类库,提供领域驱动设计(DDD)的基础设施、统一异常体系、仓储模式、API 响应格式和通用服务基类。作为框架的业务核心层,为 Infrastructure 层提供接口抽象和业务基础支撑。
核心特性
- ✅ DDD 实体 - Entity/AggregateRoot/ValueObject 等 DDD 基础类型
- ✅ 审计实体 - AuditableEntity/SoftDeleteEntity 通用审计字段
- ✅ 领域事件 - DomainEvent 事件驱动架构支持
- ✅ 统一异常 - 7 种业务异常类型:Business/NotFound/Validation 等
- ✅ 仓储模式 - IRepository/IReadOnlyRepository 泛型仓储接口
- ✅ 工作单元 - IUnitOfWork 事务管理抽象
- ✅ 服务基类 - BaseService/CrudService 通用 CRUD 服务
- ✅ API 响应 - ApiResponse/PagedResponse 统一响应格式
- ✅ 消息队列 - IMessagePublisher/IMessageSubscriber 消息接口抽象
- ✅ 缓存/日志 - ICacheService/ILoggerService 基础设施接口
核心组件
1. 实体与值对象 (Entities)
| 类 | 命名空间 | 说明 |
|---|---|---|
Entity<TKey> |
Healnet.Core.Entities |
实体基类:主键 Id、相等性比较、哈希码 |
AggregateRoot<TKey> |
Healnet.Core.Entities |
聚合根基类:支持领域事件收集与分发 |
ValueObject |
Healnet.Core.Entities |
值对象基类:基于属性的值相等性比较 |
AuditableEntity |
Healnet.Core.Entities |
可审计实体:创建时间、修改时间、创建人、修改人 |
SoftDeleteEntity |
Healnet.Core.Entities |
软删除实体:IsDeleted 标记 + 删除时间 |
DomainEvent |
Healnet.Core.Entities |
领域事件基类:事件发生时间戳 |
2. 异常体系 (Exceptions)
| 类 | 错误码 | 说明 |
|---|---|---|
HealnetException |
自定义 | 所有业务异常的基类 |
BadRequestException |
400 | 请求参数错误 |
BusinessException |
400 | 业务逻辑异常 |
NotFoundException |
404 | 资源未找到 |
ForbiddenException |
403 | 权限不足 |
UnauthorizedException |
401 | 未授权访问 |
ValidationException |
422 | 数据验证失败 |
3. 接口抽象 (Interfaces)
| 接口 | 命名空间 | 说明 |
|---|---|---|
IRepository<TEntity, TKey> |
Healnet.Core.Interfaces |
完整仓储接口:CRUD + 分页 + 批量操作 |
IReadOnlyRepository<TEntity, TKey> |
Healnet.Core.Interfaces |
只读仓储接口:查询 + 条件过滤 |
IUnitOfWork |
Healnet.Core.Interfaces |
工作单元接口:事务提交与回滚 |
IService<T> |
Healnet.Core.Interfaces |
服务接口基类 |
ICacheService |
Healnet.Core.Interfaces |
缓存服务接口 |
ILoggerService |
Healnet.Core.Interfaces |
日志服务接口 |
IMessagePublisher |
Healnet.Core.Interfaces |
消息发布接口 |
IMessageSubscriber |
Healnet.Core.Interfaces |
消息订阅接口 |
4. 服务基类 (Services)
| 类 | 命名空间 | 说明 |
|---|---|---|
BaseService |
Healnet.Core.Services |
服务基类:ID 验证、非空验证、日志记录 |
CrudService |
Healnet.Core.Services |
CRUD 服务基类:增删改查通用实现 |
5. API 响应 (Responses)
| 类 | 命名空间 | 说明 |
|---|---|---|
ApiResponse |
Healnet.Core.Responses |
统一 API 响应:Code/Message/Data/Timestamp/Path |
ApiResponse<T> |
Healnet.Core.Responses |
泛型 API 响应:强类型 Data 字段 |
PagedResponse<T> |
Healnet.Core.Responses |
分页响应:TotalCount/Page/PageSize/Items |
6. 其他模块
| 模块 | 说明 |
|---|---|
Middleware/ExceptionHandlerMiddleware |
全局异常处理中间件 |
Filters/IdempotentAttribute |
幂等性过滤器 |
Versioning/ApiVersionAttribute |
API 版本控制特性 |
Outbox/OutboxMessage |
出站消息(分布式事务 Outbox 模式) |
Features |
CQRS 命令/查询特性定义 |
Filters |
请求过滤器基类 |
Middleware |
中间件抽象 |
Filtering |
过滤功能扩展 |
Context |
上下文抽象 |
依赖关系
graph LR
A[Healnet.Core] --> B[Healnet.Common]
A --> C[Microsoft.Extensions.Logging.Abstractions]
A --> D[Microsoft.AspNetCore.Http.Abstractions]
使用指南
1. 创建实体
using Healnet.Core.Entities;
// 基础实体
public class User : Entity<long>
{
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
// 可审计实体
public class Product : AuditableEntity
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}
// 软删除实体
public class Article : SoftDeleteEntity
{
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
}
2. 统一异常处理
using Healnet.Core.Exceptions;
// 业务异常
throw new BusinessException("库存不足");
// 资源未找到
throw new NotFoundException($"用户 {userId} 不存在");
// 验证失败
throw new ValidationException(new List<string> { "邮箱格式不正确" });
// 权限不足
throw new ForbiddenException("无权访问此资源");
3. API 响应格式
using Healnet.Core.Responses;
// 成功响应
return Ok(ApiResponse.Success("操作成功"));
// 带数据的成功响应
return Ok(ApiResponse<User>.Success(user, "查询成功"));
// 错误响应
return BadRequest(ApiResponse.Error(400, "参数错误"));
// 分页响应
var paged = PagedResponse<User>.Create(users, page, pageSize, totalCount);
return Ok(paged);
4. 仓储接口
using Healnet.Core.Interfaces;
public interface IUserRepository : IRepository<User, long>
{
Task<User?> GetByEmailAsync(string email);
Task<IEnumerable<User>> GetActiveUsersAsync();
}
5. 服务基类
using Healnet.Core.Services;
using Healnet.Core.Interfaces;
public class UserService : BaseService, IUserService
{
private readonly IRepository<User, long> _repository;
public UserService(ILoggerService logger, IRepository<User, long> repository)
: base(logger)
{
_repository = repository;
}
public async Task<User> GetByIdAsync(long id)
{
ValidateId(id); // 内置 ID 验证
var user = await _repository.GetByIdAsync(id);
if (user is null)
throw new NotFoundException($"用户 {id} 不存在");
return user;
}
}
6. 全局异常处理中间件
// Program.cs
app.UseMiddleware<ExceptionHandlerMiddleware>();
NuGet 包信息
| 属性 | 值 |
|---|---|
| PackageId | Healnet.Core |
| 当前版本 | 1.5.0 |
| 目标框架 | net10.0 |
| 依赖项目 | Healnet.Common |
| 许可证 | LICENSE |
| 仓库 | github.com/healnet/healnet-framework |
版本历史
| 版本 | 日期 | 变更说明 |
|------|------|----------|
| v1.5.0 | 2026-06-16 | 新增 AggregateRoot<T>、ValueObject、DomainEvent;增强 ExceptionHandlerMiddleware 覆盖所有异常类型;移除 Newtonsoft.Json 依赖 |
| v1.4.0 | - | 版本统一升级 |
}
// 值对象 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. 创建仓储
```csharp
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) │
└─────────────────────────────────────────────────────────────┘
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Healnet.Common (>= 2.0.0)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.2.0 && < 3.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.0 && < 11.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Healnet.Core:
| Package | Downloads |
|---|---|
|
Healnet.Infrastructure
Healnet.Infrastructure 是 Healnet 框架的基础设施层类库,提供各种基础设施服务的封装和集成,包括 Consul 服务发现、Redis 缓存、RabbitMQ 消息队列、gRPC、Elasticsearch、Milvus 向量数据库、SQLSugar ORM、JWT 认证、YARP 反向代理、OpenTelemetry 可观测性、Serilog 日志框架、ClickHouse 列式数据库等。 |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0 | 42 | 7/16/2026 |
| 2.0.7 | 99 | 7/10/2026 |
| 2.0.5 | 99 | 7/8/2026 |
| 2.0.3 | 107 | 6/30/2026 |
| 2.0.0 | 111 | 6/29/2026 |
| 1.7.3 | 104 | 6/29/2026 |
| 1.5.0 | 132 | 6/16/2026 |
| 1.4.0 | 109 | 6/15/2026 |
| 1.2.0 | 110 | 5/29/2026 |
| 1.1.1 | 106 | 5/25/2026 |
| 1.1.0 | 113 | 5/22/2026 |
| 1.0.9 | 116 | 5/20/2026 |
| 1.0.8 | 104 | 5/20/2026 |
| 1.0.7 | 101 | 5/20/2026 |
| 1.0.6 | 134 | 5/19/2026 |
| 1.0.5 | 152 | 5/13/2026 |
| 1.0.4 | 114 | 5/13/2026 |
| 1.0.3 | 119 | 5/13/2026 |
| 1.0.2 | 110 | 5/13/2026 |
| 1.0.1 | 112 | 5/13/2026 |
v1.5.0: 新增 AggregateRoot<T>/ValueObject/DomainEvent;增强 ExceptionHandlerMiddleware 覆盖所有异常类型;移除 Newtonsoft.Json 依赖