Healnet.Core 2.0.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package Healnet.Core --version 2.0.3
                    
NuGet\Install-Package Healnet.Core -Version 2.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Healnet.Core" Version="2.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Healnet.Core" Version="2.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Healnet.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Healnet.Core --version 2.0.3
                    
#r "nuget: Healnet.Core, 2.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Healnet.Core@2.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Healnet.Core&version=2.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Healnet.Core&version=2.0.3
                    
Install as a Cake Tool

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>ValueObjectDomainEvent;增强 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed

v2.0.3: 统一三库版本号;升级目标框架至 net10.0;更新所有依赖包至最新稳定版。v2.0.1: 依赖包版本升级,修复若干已知问题。v2.0.0: 重大版本更新,目标框架从 net8.0 升级至 net10.0,全面更新依赖包版本。