Galosys.Foundation.Core
26.9.10.1
dotnet add package Galosys.Foundation.Core --version 26.9.10.1
NuGet\Install-Package Galosys.Foundation.Core -Version 26.9.10.1
<PackageReference Include="Galosys.Foundation.Core" Version="26.9.10.1" />
<PackageVersion Include="Galosys.Foundation.Core" Version="26.9.10.1" />
<PackageReference Include="Galosys.Foundation.Core" />
paket add Galosys.Foundation.Core --version 26.9.10.1
#r "nuget: Galosys.Foundation.Core, 26.9.10.1"
#:package Galosys.Foundation.Core@26.9.10.1
#addin nuget:?package=Galosys.Foundation.Core&version=26.9.10.1
#tool nuget:?package=Galosys.Foundation.Core&version=26.9.10.1
Galosys.Foundation.Core
成熟度: 🟢 稳定 — 生产可用,测试充分,活跃维护
Galosys.Foundation 核心库,提供统一响应模型、DDD 实体基类、扩展方法、安全加密、消息总线、模块化机制等基础能力。
特性一览
| 领域 | 功能 |
|---|---|
| 统一响应 | UnifiedResponse 成功/失败/异常/处理中 |
| DDD 实体 | Entity / FullEntity / TenantEntity / AppEntity + 领域事件 |
| ID 生成 | Snowflake、LocalGenerator、Nanoid、Ulid、Uuid |
| 分页 | PageOutput、PageQuery 分页查询基类 |
| 消息 | 事件订阅/发布、IMessageBus + Outbox 引擎 |
| COLA 架构 | Executor 模板方法、ExtensionPoint 扩展点、PluginRegistry |
| CQRS Lite | ICommand<TResult> / ICommandHandler<,> / ICommandBus 接口 + CommandBus 反射编译实现 + AddCqrs() 一键注册 + 命令级 Telemetry + IValidator<T> 校验 + Castle AOP 横切 |
| Resilience 弹性 | 重试/熔断/超时/隔离/限流/降级(Polly 实现) |
| State Machine | 三泛型状态机 + Builder DSL + 持久化 |
| Rules Engine | 规则引擎 + 构建器 + 回退链 |
| 分布式锁 | IDistributedLock 抽象 + 内存实现 |
| 分布式幂等 | IDistributedIdempotence 接口 |
| 告警 | IAlarmer 告警日志基础设施 |
| AI 集成 | 通义千问 Embedding |
| Excel 操作 | IXlsHelper 流式读/写/模板填充 |
| 数据结构 | BloomFilter、WorkerPool、ChannelTemplate、责任链 |
| 工具类 | Env、ServiceLocator、Poco、Tree、ITimeProvider、数据脱敏、签名等 |
| 模块化 | 编译时 SourceGen + 运行时双模式模块发现 |
| DI 上下文 | ITenantContext / IAppContext / IUserContext |
1. 统一响应模型
// 成功响应
var response = UnifiedResponse.Succeed(data, "操作成功");
// 失败响应
var response = UnifiedResponse.Fail("ERROR_CODE", "操作失败");
// 异常响应
var response = UnifiedResponse.Error("ERROR_CODE", exception);
// 处理中
var response = UnifiedResponse.Processing("PROCESSING_CODE");
2. 实体与 DDD 模式
// 完整实体(含创建者、修改者、软删除)
public class User : FullEntity<long>
{
public string Name { get; set; }
}
// 基础实体
public class Entity
{
public IReadOnlyCollection<ApplicationMessage> DomainEvents { get; }
protected void AddEvent(ApplicationMessage @event) { }
}
实体基类矩阵
Entity (abstract, 领域事件)
└── Entity<TID> (abstract, [Key, SnowflakeId] Id)
├── FullEntity<TID> (abstract, IDeletable + ICreator + ILastModifier)
│ ├── TenantEntity<TID> : FullEntity<TID>, IMultiTenancy
│ ├── AppEntity<TID> : FullEntity<TID>, IMultiApplication
│ └── TenantAppEntity<TID> : FullEntity<TID>, IMultiTenancy, IMultiApplication
| 基类 | 适用场景 | 示例 |
|---|---|---|
FullEntity<TID> |
全局基础数据,不分租户和应用 | 地区、字典、系统配置 |
TenantEntity<TID> |
仅分租户 | 用户、角色、权限 |
AppEntity<TID> |
仅分应用 | 菜单、API 接口 |
TenantAppEntity<TID> |
租户 + 应用 | 租户应用配置 |
实体可混入 IConcurrency 实现乐观并发控制:
public class SysUser : TenantEntity<long>, IConcurrency
{
[Timestamp]
public byte[] RowVersion { get; protected set; } = null!;
}
L2 形态 — 领域事件自动分发
聚合根继承 Entity 基类即具备 DomainEvents 收集能力(AddEvent / ClearEvents,实现 IHasDomainEvents 标记接口)。启用 AddEfCoreOutboxStore<T>() 后,EF SaveChanges 成功时拦截器自动把事件发布到进程内订阅者(IApplicationListener<T>)。
// 聚合根:业务方法收集事件
public sealed class Order : FullEntity<long>
{
public Order Place(long customerId, List<OrderItem> items)
{
...
AddEvent(new OrderPlaced(this));
return this;
}
}
// Handler:无任何事件相关标注,正常持久化即可
[Transactional]
public sealed class PlaceOrderHandler : ICommandHandler<PlaceOrderCommand, long>
{
public async Task<long> HandleAsync(PlaceOrderCommand cmd, CancellationToken ct = default)
{
var order = Order.Place(...);
_db.Orders.Add(order);
await _db.SaveChangesAsync(ct); // ← 保存成功后拦截器自动发布 OrderPlaced
return order.Id;
}
}
// 订阅方:实现 IApplicationListener<T> 即自动接收(AddApplicationMessagePublisher 扫描注册)
public sealed class OrderPlacedListener : IApplicationListener<OrderPlaced>
{
public Task<bool> HandleAsync(OrderPlaced e)
{
// 读模型更新 / 进程内通知
return Task.FromResult(true);
}
}
注册:services.AddEfCoreOutboxStore<ApplicationDbContext>();(一并启用进程内事件分发 + 跨服务 Outbox;未启用 Outbox store 时也可手动 TryAddSingleton<DomainEventSaveChangesInterceptor>() 并确保发布器已注册)
跨服务集成事件不走本机制——Handler 内显式 IMessageBus.PublishAsync(routingKey, event)(Outbox → MQ,事务一致)。
3. ID 生成
// 雪花算法 ID
var id = SnowflakeIdGenerator.Instance.NextId();
// 本地 ID 发生器
var id = LocalGenerator.NextId();
var couponKey = LocalGenerator.NextCouponKey();
var seqKey = LocalGenerator.NextSeqKey();
var guid = LocalGenerator.NextGuid();
此外支持多种 ID 策略(通过特性标注实体字段):
[Nanoid] // Nanoid 字符串 ID
[Ulid] // ULID 有序唯一标识
[Uuid] // UUID 标识
4. 分页
var pageResult = PageOutput.Of(items, total, page, size);
5. 单例模式
// 线程安全的延迟初始化单例
var instance = Singleton<MyService>.GetInstance();
// 使用 Lazy<T> 的单例
var instance = LazySingleton<MyService>.Instance;
6. 消息订阅/发布
// 发布消息
await publisher.PublishAsync(new UserCreatedEvent(this));
// 订阅消息
public class UserCreatedListener : ApplicationListener<UserCreatedEvent>
{
public override Task<bool> HandleAsync(UserCreatedEvent e)
{
return Task.FromResult(true);
}
}
7. 扩展方法
// DateTime 扩展
var lastDay = dt.LastDayInMonth();
var firstDay = dt.FirstDayInMonth();
var isWeekend = dt.IsWeekend();
var workDate = dt.AddWorkDays(3);
var unixMs = dt.ToUnixTimeMilliseconds();
var unixSec = dt.ToUnixTimeSeconds();
var datetime = timestamp.ToDateTime();
// String 扩展
var compressed = "content".ToGZipCompress();
var decompressed = compressed.ToGZipDecompress();
// Object 扩展
var result = obj.GetAsyncResult<Task<string>>();
// IQueryable 扩展
queryable.WhereIf(condition, x => x.IsActive)
.Page(pageIndex, pageSize);
// 集合扩展
list.Shuffle();
list.TopologicalSort(selector);
list.Slice(5);
list.BinaryInsertSort(item, comparer);
8. 安全加密
// MD5 加密
var hashed = SecurityTemplate.Md5Encrypt(original);
// DES 加解密
var encrypted = SecurityTemplate.DesEncrypt(original);
var decrypted = SecurityTemplate.DesDecrypt(encrypted);
// AES 加解密
var encrypted = SecurityTemplate.AesEncrypt(original, key);
var decrypted = SecurityTemplate.AesDecrypt(encrypted, key);
// RSA 加解密
var encrypted = SecurityTemplate.RSAEncrypt(original, publicKey);
var decrypted = SecurityTemplate.RSADecrypt(encrypted, privateKey);
// 许可证生成与验证
var license = SecurityTemplate.GenerateLicense(info);
var valid = SecurityTemplate.ValidateLicense(license);
9. 动态代理
class HttpProxy : ServiceProxy
{
protected override void Proceed(InvocationContext context)
{
var http = context.ServiceProvider.GetRequiredService<IHttpClientFactory>().CreateClient();
context.SetReturnValue(http.GetStringAsync("/posts/1"));
}
}
var instance = ServiceProxyFactory.CreateProxy(typeof(ITypicodeClient), typeof(HttpProxy), sp) as ITypicodeClient;
10. 进程管理
// 启动进程
var p = new Process().Start("cmd.exe", runAsAdministrator: true);
// 打开浏览器
p = new Process().Browser("https://example.com");
// 打开资源管理器
p = new Process().Explore("c://");
// 执行脚本
p = new Process().Script("dotnet.exe", "info");
11. HTTP 客户端
services.AddHttpClient<IPlaceholderGateway, PlaceholderGateway>(http =>
{
http.BaseAddress = new Uri("https://jsonplaceholder");
}).AddServiceDiscovery()
.AddStandardHedgingHandler();
12. 验证码生成
var code = Random.Shared.GenerateCaptcha(); // 验证码
var sms = Random.Shared.GenerateSms(); // 短信验证码
13. 应用程序启动器
public class MyRunner : IApplicationRunner
{
public int Order => 0;
public async Task RunAsync(ApplicationArguments args) { }
}
14. PluginRegistry(插件注册表)
基于策略路由模式的基础设施,根据请求自动匹配对应插件实现。适用于短信网关、支付渠道、物流商等多 provider 场景。
public interface ISmsPlugin : Plugin<SmsRequest>
{
Task SendAsync(SmsRequest request);
}
internal class AliyunSmsPlugin : ISmsPlugin
{
public bool Supports(SmsRequest request) => request.Provider == "aliyun";
public Task SendAsync(SmsRequest request) { /* ... */ }
}
// DI 注册
services.AddTransient<ISmsPlugin, AliyunSmsPlugin>();
// 使用
var registry = serviceProvider.GetRequiredService<PluginRegistry<ISmsPlugin, SmsRequest>>();
var plugin = registry.GetPluginFor(request);
await plugin.SendAsync(request);
| 模式 | 行为 |
|---|---|
GetPluginFor |
单匹配 — 返回第一个匹配插件 |
GetAllPluginsFor |
多匹配 — 返回所有匹配插件(广播场景) |
PluginResolutionMode.Scoped |
默认,创建新 DI Scope |
PluginResolutionMode.Singleton |
从根容器直接获取 |
15. Executor 模板方法
提供命令执行管道(仅异步),按顺序执行:前置钩子 → 参数校验 → 业务逻辑 → 后置钩子,统一返回 Task<UnifiedResponse>。AddCola() 会自动扫描并注册(Scoped)所有 IExecutor<TCommand> 实现,无需手工注册。
// 注册(自动扫描当前运行时程序集中的扩展点与 IExecutor<TCommand> 实现)
services.AddCola();
// 定义命令(重写异步校验)
public class OrderCreateCmd : CommandBase
{
public string OrderNo { get; set; }
public override Task<ValidationResult> ValidateAsync(CancellationToken ct = default) { /* ... */ }
}
// 实现 Executor(仅需实现异步业务逻辑)
public class OrderCreateExecutor : ExecutorBase<OrderCreateCmd>
{
public OrderCreateExecutor(ILogger<ExecutorBase<OrderCreateCmd>> logger, IServiceProvider sp) : base(logger, sp) { }
protected override Task<UnifiedResponse> DoExecuteAsync(OrderCreateCmd command, CancellationToken ct)
{
return Task.FromResult(UnifiedResponse.Succeed(new { OrderId = Guid.NewGuid() }));
}
}
// 显式注入并异步执行
var executor = sp.GetRequiredService<IExecutor<OrderCreateCmd>>();
UnifiedResponse result = await executor.ExecuteAsync(cmd);
| 阶段 | 方法 | 说明 |
|---|---|---|
| 前置钩子 | OnBeforeExecuteAsync |
记录日志,可重写 |
| 参数校验 | command.ValidateAsync() |
失败返回 VALIDATION_ERROR |
| 业务逻辑 | DoExecuteAsync |
子类必须实现 |
| 后置钩子 | OnAfterExecuteAsync |
记录日志,可重写 |
| 业务异常 | HandleBusinessException |
捕获 BizException |
| 系统异常 | HandleSystemException |
返回 SYSTEM_ERROR |
16. CQRS Lite
轻量级 Command/Query 分离抽象——与 Cola Executor 双轨并行,按"业务场景复杂度"选择使用。
双轨定位:简单 CRUD / 单一横切 → Cola Executor;≥3 横切 / Outbox 原子保证 / 领域事件衔接 → CQRS Dispatcher。详见
docs/designs/capability-gap-and-action-plan.md附录 A。
16.1 接口契约
// 命名空间:Galosys.Foundation.Core(命名空间寄生:依赖 ICommand<TResult> 同处 Core)
public interface ICommand<TResult> : ICommand { } // 继承富接口(RequestId/UserId/TraceId/Validate)
// 命名空间:Galosys.Foundation.Core
public interface ICommandHandler<in TCommand, TResult>
where TCommand : ICommand<TResult>
{
Task<TResult> HandleAsync(TCommand command, CancellationToken ct = default);
}
// 命名空间:Galosys.Foundation.Core(命令总线:dispatcher 仅承载 Command 一侧,命名规范对齐 MediatR ISender / Brighter IAmACommandProcessor / MassTransit IBus)
public interface ICommandBus
{
Task<TResult> SendAsync<TResult>(ICommand<TResult> command, CancellationToken ct = default);
}
16.2 使用示例
// 1) 定义命令(继承 CommandBase,自动获得 ICommand 富接口成员)
public sealed class CreateOrderCommand : CommandBase, ICommand<OrderId>
{
public string Sku { get; set; } = string.Empty;
public int Quantity { get; set; }
}
public readonly record struct OrderId(long Value);
// 2) 实现 Handler
public sealed class CreateOrderHandler : ICommandHandler<CreateOrderCommand, OrderId>
{
private readonly IOrderRepository _repository;
public CreateOrderHandler(IOrderRepository repository) => _repository = repository;
public async Task<OrderId> HandleAsync(CreateOrderCommand cmd, CancellationToken ct = default)
{
var order = new Order { Sku = cmd.Sku, Quantity = cmd.Quantity };
await _repository.AddAsync(order, ct);
return new OrderId(order.Id);
}
}
// 3) DI 注册(一行扫所有 ICommandHandler<,>;也可省略——AddCore() 已自动调用 AddCqrs)
services.AddCqrs();
// 4) 注入并使用
public class OrderController(ICommandBus bus)
{
public async Task<OrderId> Create(CreateOrderCommand cmd)
{
return await bus.SendAsync(cmd); // 返回裸 TResult(Controller 自行包装 UnifiedResponse)
}
}
16.3 Dispatcher 行为
| 行为 | 实现细节 |
|---|---|
| 首次调用 | 通过 Expression.Lambda 编译 Func<IServiceProvider, object, CancellationToken, Task<TResult>>,固化到 ConcurrentDictionary<Type, Func<>> |
| 后续调用 | 直接字典查询,零反射 |
| Handler 解析 | sp.GetService(ICommandHandler<TCommand, TResult>) |
| 异常透传 | Handler 抛出的异常完全透传(不包装、不记录日志) |
| 未注册 Handler | 抛 InvalidOperationException,消息含命令 FullName 与 services.AddCqrs() 注册提示 |
16.4 与 Executor 的取舍
| 维度 | Cola Executor | CQRS Dispatch |
|---|---|---|
| 返回类型 | Task<UnifiedResponse> |
Task<TResult> |
| 横切挂载 | 继承基类 + 重写 OnBefore/OnAfter |
Castle AOP Attribute([Transactional] / [Retryable]) |
| 异常处理 | 基类 catch + 翻译 UnifiedResponse.Fail |
透传 |
| BizScenario 扩展 | ✅ 内置 | ❌ 无 |
| 命令→Handler 1:1 | ✅ 显式 Executor 注入 | ✅ CommandBus 按命令类型解析 |
16.5 当前阶段(Phase 1 + 1.1 + Phase 2)
- ✅ 接口定义(
ICommand<TResult>/ICommandHandler<,>/ICommandBus),全部位于Galosys.Foundation.Core命名空间 - ✅
CommandBus反射编译实现 +AddCqrs()DI 注册 - ✅ Phase 2:命令级 Telemetry(
ActivitySource("Galosys.Foundation.Cqrs", "1.0.0")) +IValidator<T>直接注入校验 + Castle AOP 横切([Transactional]/[Retryable])。不引入IPipelineBehavior中间件链——横切统一走框架既有 Castle AOP,校验在 Handler 内显式调用 - ✅ Phase 2 端到端示例:
samples/Dev.ConsoleApp/CQRS_SAMPLE.md - ✅ Phase 3:领域事件 EF SaveChanges 拦截器自动分发(
DomainEventSaveChangesInterceptor,随AddEfCoreOutboxStore<T>()启用);集成事件维持IMessageBus.PublishAsync处理器决策 - ⏳ Phase 4:注入式查询类(
OrderQueries) - ⏳ Phase 5:Native AOT 源生成器 + samples
16.6 命令级链路追踪(Telemetry)
CommandBus.SendAsync<TResult> 内置 OpenTelemetry 链路追踪,无需任何中间件:
// DI 注册(默认 EnableCqrsTelemetry = true,可显式关闭)
services.AddCqrs(o => o.EnableCqrsTelemetry = true);
// OpenTelemetry 侧需注册同名 Source 才能采集到 Span
builder.Services.AddOpenTelemetry()
.WithTracing(t => t.AddSource("Galosys.Foundation.Cqrs"));
- 每个
SendAsync调用创建一个Activity,Span 名称为cqrs.sendAsync/{命令运行时类型名} - Tag:
cqrs.command= 命令FullName,cqrs.result_type=typeof(TResult).Name - Handler 抛异常时 Span 状态标记为
Error - 全局开关另可经
CommandBusTelemetry.Enabled静态属性控制
16.7 业务规则校验(Validation)
校验抽象独立于 CQRS,命名空间寄生于 Microsoft.Extensions.Validation(.NET 10 官方包,10.0.11),默认实现 DataAnnotationsValidator<T> 桥接官方源生成器 + BCL System.ComponentModel.DataAnnotations 回退:
// 1) 命令属性打 DataAnnotations 特性(BCL,无需额外 NuGet)
// 或打 [ValidatableType] 走官方源生成器
public sealed class CreateOrderCommand : CommandBase, ICommand<OrderId>
{
[Required] public string Sku { get; set; } = string.Empty;
[Range(1, int.MaxValue)] public int Quantity { get; set; }
}
// 2) Handler 构造注入 IValidator<T>,HandleAsync 开头显式校验(fail-fast)
public sealed class CreateOrderHandler : ICommandHandler<CreateOrderCommand, OrderId>
{
private readonly IValidator<CreateOrderCommand> _validator;
public CreateOrderHandler(IValidator<CreateOrderCommand> validator) => _validator = validator;
public async Task<OrderId> HandleAsync(CreateOrderCommand cmd, CancellationToken ct = default)
{
var result = await _validator.ValidateAsync(cmd, ct);
if (!result.IsValid)
throw new BizException(string.Join("; ", result.Errors.SelectMany(e => e.Errors)));
// ...
}
}
通用入口 AddValidationCore()(寄生 Microsoft.Extensions.DependencyInjection):
// Program.cs / Startup.cs
builder.Services.AddValidationCore(options =>
{
options.MaxDepth = 32; // 嵌套校验深度上限
});
// 等价于:services.AddValidation(options => ...); // 官方
// services.TryAddTransient(typeof(IValidator<>), typeof(DataAnnotationsValidator<>)); // 我们
三种典型使用姿势(不与 CQRS 耦合):
// 姿势 1:仅 CQRS(AddCqrs 已隐含注册 IValidator<T> 默认实现)
services.AddCqrs();
// 姿势 2:CQRS + 自定义 ValidationOptions
services.AddValidationCore(o => o.MaxDepth = 64);
services.AddCqrs();
// 姿势 3:非 CQRS 业务(任意场景)
services.AddValidationCore();
services.AddTransient<IValidator<MyDto>, MyCustomValidator>();
AddCqrs自动注册开放泛型IValidator<>→DataAnnotationsValidator<>(TryAddTransient幂等,可被AddValidationCore/ 自定义注册覆盖)- 引擎可替换:注册具体
IValidator<MyDto>实现可覆盖默认;上层可叠加 FluentValidation 等
⚠️ BREAKING 变更(自 26.9 版本起):
IValidator<T>/IValidationResult命名空间由Galosys.Foundation.Core迁至Microsoft.Extensions.Validation- 自定义
ValidationError(MemberName, ErrorMessage)已删除;IValidationResult.Errors元素类型改用官方Microsoft.Extensions.Validation.ValidationErrorContext:
| 旧字段(已删除) | 新字段(官方) | 说明 |
|---|---|---|
MemberName |
Name |
字段或参数名 |
ErrorMessage |
Errors(IReadOnlyList<string>) |
多消息列表(原单字符串 → 列表) |
| — | Path |
嵌套属性路径(新增) |
| — | Container |
被校验对象引用(新增;JSON 序列化时需排除避免循环引用) |
调用方需将 result.Errors.Select(e => e.ErrorMessage) 改为 result.Errors.SelectMany(e => e.Errors)。
序列化注意:ValidationErrorContext.Container 持有被校验对象引用,JSON 序列化时必须排除;可使用 ValidationErrorContextExtensions.WithoutContainer() 投影(寄生扩展位于 Microsoft.Extensions.Validation 命名空间)。
16.8 完整示例与选型
- 端到端示例:
samples/Dev.ConsoleApp/CQRS_SAMPLE.md—— 命令 + Handler + Castle AOP 横切 +IValidator<T>注入校验 + Outbox 自动 flush + OpenTelemetry 链路追踪,非 HTTP 入口([HostedService]Worker)派发命令 - 何时启用 CQRS:见决策树
docs/designs/capability-gap-and-action-plan.md(附录 A.4 决策指南)。默认推荐 Cola Executor(简单 CRUD / 强一致);仅当需要 Outbox 原子保证、BizScenario 扩展、≥3 个横切、裸TResult返回时才选 CQRS Lite。横切一律经 Castle AOP Attribute 挂载,而非IPipelineBehavior
17. ExtensionPoint(扩展点机制)
基于 COLA 架构的扩展点模式,通过 BizScenario(业务身份)路由到不同的扩展点实现。
public interface IPaymentStrategy : IExtensionPoint
{
Task<PaymentResult> PayAsync(PaymentRequest request);
}
[Extension(BizId = "default", UseCase = "default", Scenario = "wechat")]
public class WechatPaymentStrategy : IPaymentStrategy { /* ... */ }
// 使用
var scenario = BizScenario.ValueOf("default", "default", paymentType);
var result = await executor.ExecuteAsync<IPaymentStrategy, PaymentResult>(
scenario, svc => svc.PayAsync(request));
匹配降级策略:精确匹配 → 场景通配 → 用例通配 → 全局默认。
支持批量执行(ExecuteAll / ExecuteAllAsync)和归约(ReduceAsync)。
18. PageQuery(分页查询基类)
var query = new PageQuery
{
PageIndex = 2,
PageSize = 10,
};
query.SetOrderDirection("ASC");
int offset = query.Offset; // 10
| 属性 | 说明 | 默认 |
|---|---|---|
PageIndex |
页码(最小1) | 1 |
PageSize |
每页大小(最小1) | 10 |
Offset |
偏移量(只读) | (PageIndex-1)*PageSize |
OrderDirection |
排序方向 | "DESC" |
19. MessageBus + Outbox 引擎
提供 IMessageBus 统一消息入口(Send + Publish),以及 Transactional Outbox 模式保证业务事务与消息发送的原子性。
// 进程内默认总线
await bus.PublishAsync("order.created", order);
// 实现消息处理器
public class OrderCreatedHandler : IMessageHandler<OrderCreatedEvent>
{
public Task<bool> HandleAsync(OrderCreatedEvent msg) { /* ... */ }
}
// DI 注册
services.AddScoped<IMessageHandler<OrderCreatedEvent>, OrderCreatedHandler>();
Outbox 模式: PendingMsgCol 收集待发送消息,DbContext.DrainPendingOutbox() 在 SaveChanges 时同事务写入 base_outbox_msg 表(列名 snake_case),后台 OutboxRelay 轮询投递。
性能优化(Phase 2): OutboxMessage 新增 Version 字段支持乐观锁,IOutboxStore 新增 TryAcquireBatchAsync / MarkManySentAsync / MarkManyFailedAsync 批量 API,OutboxRelay 改为 TryAcquireBatch → Parallel.ForEachAsync(DOP=4)→ MarkMany 流水线,吞吐目标 200-500/s。
services.AddRabbitMessageBus(options => {
options.EnableOutbox = true;
options.Outbox.DefaultMode = "Outboxed"; // 默认走 outbox
});
services.AddEfCoreOutboxStore<MyDbContext>();
| 配置项 | 默认值 | 说明 |
|---|---|---|
EnableOutbox |
true |
全局 outbox 开关 |
TableName |
"base_outbox_msg" |
发件箱表名(列名 snake_case) |
SchemaName |
"base" |
数据库 schema |
DefaultMode |
"Outboxed" |
路由默认策略:"Outboxed"=走 outbox,"Direct"=直发 |
MaxRetryCount |
3 |
最大重试次数(0=不限) |
BatchSize |
500 |
每次轮询拉取数 |
PollIntervalMs |
500 |
轮询间隔(ms) |
RetentionDays |
7 |
已发送消息保留天数 |
| 组件 | 说明 |
|---|---|
IMessageBus |
统一消息入口 |
PendingMsgCol |
AsyncLocal 消息收集器 |
OutboxSaveChangesInterceptor |
EF Core 保存拦截器 |
OutboxRelay |
后台轮询投递服务 |
OrphanedCleanupService |
孤儿消息清理 |
OutboxMeter |
OpenTelemetry 指标(含 outbox.orphaned.total 未落库丢弃计数) |
OutboxMeter 指标一览:
| 指标名 | 类型 | 说明 |
|---|---|---|
outbox.sent.total |
Counter | 累计发送成功数 |
outbox.failed.total |
Counter | 累计发送失败数 |
outbox.retry.exhausted |
Counter | 重试耗尽丢弃数 |
outbox.orphaned.total |
Counter | 累计未落库丢弃数 — PublishAsync 后未调 SaveChanges 导致消息丢失时递增 |
outbox.scan.duration |
Histogram | 单次轮询耗时(ms) |
outbox.pending.count |
ObservableGauge | 待发送消息数 |
20. 上下文服务(DI)
框架内置 ITenantContext、IAppContext、IUserContext 三个 Singleton 上下文服务,基于 AsyncLocal<T> 实现请求级隔离。
public class MyService
{
public MyService(ITenantContext tenant, IAppContext app, IUserContext user) { }
}
21. 多租户(Multi-Tenancy)
框架提供多层防御的多租户体系:行级隔离 + fail-secure 默认 + 显式系统模式 + 表级与插入级穿透。设计依据 ADR-0004 与 ADR-0005。
21.1 三态上下文(fail-secure 默认)
ITenantContext 有三个互斥状态,未显式初始化时默认安全(fail-secure):
IsSystemContext |
TenantId |
含义 | 过滤器行为 |
|---|---|---|---|
false |
null |
未初始化 | 抛 InvalidOperationException |
false |
>0 |
正常租户 | 按 TenantId 过滤 |
true |
null |
系统/总后台 | 穿透,返回所有租户数据 |
using Galosys.Foundation.Core;
// 场景1:正常业务(中间件已 SetTenant)
public class OrderService(ITenantContext ctx)
{
public Task<List<Order>> GetCurrent() => db.Orders.ToListAsync();
// 过滤器自动按 ctx.TenantId 过滤
}
// 场景2:跨租户查询(系统后台)
public class GlobalAdminService(ITenantContext ctx, DbContext db)
{
public async Task<List<Order>> GetAllTenantsOrders()
{
using (ctx.EnterSystemContext()) // 显式 opt-in
{
// IsSystemContext=true,过滤器穿透
return await db.Orders.ToListAsync();
}
// 作用域结束,自动还原
}
}
// 场景3:未初始化调用 → 抛异常(fail-secure)
public async Task CrashDemo()
{
// 没有中间件、没有 SetTenant
var orders = await db.Orders.ToListAsync();
// InvalidOperationException: 未初始化,调用 Change() 或 EnterSystemContext()
}
21.2 租户元数据 POCO
using Microsoft.Extensions.MultiTenancy;
// 普通租户
var tenant = new Tenant
{
Id = 1,
Identifier = "acme",
Name = "Acme Corporation",
IsolationMode = TenantIsolationMode.Row,
IsActive = true
};
// 系统模式 token(不存储于 ITenantStore,仅作占位)
var sys = Tenant.System; // Identifier = "__system__"
21.3 租户存储与注册
using Microsoft.Extensions.MultiTenancy;
// 注册多租户服务(默认 InMemoryTenantStore + TenantContext)
services.AddTenancy();
// 自定义租户存储(EF Core 实现)
public class EfCoreTenantStore : ITenantStore
{
public Task<Tenant?> GetByIdentifierAsync(string id, CancellationToken ct = default)
=> db.Tenants.FirstOrDefaultAsync(t => t.Identifier == id, ct);
public Task<Tenant?> GetByIdAsync(long id, CancellationToken ct = default)
=> db.Tenants.FirstOrDefaultAsync(t => t.Id == id, ct);
}
services.AddSingleton<ITenantStore, EfCoreTenantStore>();
21.3.1 MultiTenancyStoreOptions(可配置目标表)
MultiTenancyStoreOptions 用于覆盖租户元数据表的目标 schema 与表名,默认行为与历史一致(Schema = null,TableName = "mt_tenant"),零破坏。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
Schema |
string? |
null |
schema 名;null/空 → 单参 ToTable(name),非空 → 双参 ToTable(name, schema) |
TableName |
string |
"mt_tenant" |
表名;未配置兜底 MultiTenancyStoreConstants.TableName |
ADR-0001 规则 4:表名/列名仍以
MultiTenancyStoreConstants为单一常量来源,MultiTenancyStoreOptions仅在消费方显式配置时覆盖。
典型用例:指向平台统一租户表 uc.uc_tenant
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.MultiTenancy;
services.AddEfCoreTenantStore<MyDbContext>(o =>
{
o.Schema = "uc";
o.TableName = "uc_tenant";
});
uc.uc_tenant 表由平台侧(UC 团队)负责创建与迁移,本仓库只消费。
21.4 多层穿透机制
using Galosys.Foundation.Core;
// ===== 1. 表级穿透:IGlobalEntity =====
// 系统字典、菜单等全局表:不参与多租户过滤
public class SysDict : Entity, IGlobalEntity // ★ 不实现 IMultiTenancy
{
public string Code { get; set; }
public string Value { get; set; }
// 无 TenantId 属性
}
// ===== 2. 插入穿透:ITenantInsertOptOut =====
// 系统后台批量导入:手动控制 TenantId,SaveChanges 不自动填充
public class SysUser : FullEntity<long>, IMultiTenancy, ITenantInsertOptOut
{
public long TenantId { get; set; } // 必须有,但 SaveChanges 不自动填
public string Name { get; set; }
}
// 在服务中
public class ImportService(ITenantContext ctx, DbContext db)
{
public async Task ImportUser(SysUser user)
{
user.TenantId = 42; // 显式指定,不依赖 ctx.TenantId
db.Users.Add(user);
await db.SaveChangesAsync(); // 不会覆盖为 ctx.TenantId
}
}
// ===== 3. 上下文系统模式:EnterSystemContext() =====
public class ReportService(ITenantContext ctx, DbContext db)
{
public async Task<List<Order>> GetCrossTenantReport()
{
using (ctx.EnterSystemContext())
{
return await db.Orders.ToListAsync(); // 跨租户
}
}
}
// ===== 4. 单次查询绕过:IgnoreQueryFilters() =====
public Task<List<Order>> GetAllIncludingSoftDeleted()
=> db.Orders.IgnoreQueryFilters().ToListAsync();
21.5 选项与迁移开关
using Galosys.Foundation.Core;
// 默认配置:fail-secure(未初始化抛异常)
services.AddTenancy();
// 迁移期配置:暂时关闭 fail-secure(仅旧后台任务需要)
services.Configure<MultiTenancyOptions>(opts =>
{
opts.ThrowOnUninitialized = false; // 关闭 fail-secure
opts.AllowLegacyZeroTenant = true; // 允许 SetTenant(0) 进入系统模式
});
// 迁移完成后立即移除此配置
21.6 解析策略与中间件
// 自定义解析策略(从 Header 解析)
public class HeaderResolutionStrategy : ITenantResolutionStrategy
{
private readonly IHttpContextAccessor _accessor;
public HeaderResolutionStrategy(IHttpContextAccessor accessor) => _accessor = accessor;
public Task<string?> ResolveIdentifierAsync(CancellationToken ct = default)
=> Task.FromResult(_accessor.HttpContext?.Request.Headers["X-Tenant-Id"].FirstOrDefault());
}
// 中间件使用(参见 AspNetCore 包)
app.UseMultiTenancy(opts => opts
.WithHeader("X-Tenant-Id") // 优先 Header
.WithHost("{tenant}.example.com") // 其次 Host
.WithStore<InMemoryTenantStore>()); // 自定义存储
21.7 选型决策
| 场景 | 推荐机制 |
|---|---|
| 静态系统表(字典、菜单) | IGlobalEntity |
| 系统后台批量导入 | ITenantInsertOptOut |
| 跨租户查询/操作 | EnterSystemContext() |
| 单次查询穿透 | IgnoreQueryFilters() |
| 正常业务 | 默认(无标记) |
详细决策树参见 docs/designs/multi-tenancy-enhancement.md 附录 A。
21.8 P2 隔离抽象层(Isolation Abstractions)
P1 已落地行级(Row)隔离。P2 引入 Schema / Database / Hybrid 隔离,Core 层先交付隔离抽象层(spec multi-tenancy-p2-isolation-abstractions),不触 EFCore/ORM;Schema / Database / Hybrid 的具体路由分别走 P2-2 / P2-3。
Tenant POCO 新增 3 个 nullable 运行时元数据字段(默认 null,EF Core 映射 Ignore,不落库):
public string? SchemaTemplate { get; set; } // 如 "uc_{id:00000000}"
public string? DatabaseTemplate { get; set; } // 如 "tenant_{id:00000000}"
public string? IsolationConnectionString { get; set; } // Database 模式专用
IsolationModeResolver:无状态服务,集中隔离决策逻辑。输入 (Tenant, MultiTenancyIsolationOptions) 输出 IsolationModeDecision { Mode, IsolationKey }。模板占位符 {id:00000000}(8 位补零,排序友好):
using Microsoft.Extensions.MultiTenancy;
var decision = resolver.Resolve(tenant, options);
// Row → IsolationKey = null
// Schema → SchemaTemplate?.Replace(...) ?? options.DefaultSchemaTemplate...
// Database → DatabaseTemplate?.Replace(...) ?? options.DefaultDatabaseTemplate...
// Hybrid → 返回 Schema 名(连接串由 DatabaseConnectionStringResolver 单独提供)
MultiTenancyIsolationOptions(DI Options,注入顺序 RemoveAll → Configure → AddScoped):
| 字段 | 默认值 | 说明 |
|---|---|---|
DefaultSchemaTemplate |
"tenant_{id:00000000}" |
Schema 模式默认模板 |
DefaultDatabaseTemplate |
"tenant_{id:00000000}" |
Database 模式默认模板 |
DatabaseConnectionStringResolver |
null |
Func<long, string?>,输入 Tenant.Id 返回连接串;null 时 Database 模式 fail-secure |
ISchemaTenantAccessor:按当前租户解析 Schema 名(Schema 隔离必备;Row 返回 null)。
ITenantIsolationContext(Scoped,跟随 ITenantContext 自动重算):当前请求的隔离上下文,暴露 Current / Mode / IsolationKey / ConnectionString。ITenantContext.Current 未初始化时抛 InvalidOperationException(继承 ADR-0004 fail-secure)。
DI 注册入口:
using Microsoft.Extensions.DependencyInjection;
services.AddMultiTenancyIsolationCore();
services.Configure<MultiTenancyIsolationOptions>(o =>
{
o.DefaultSchemaTemplate = "uc_{id:00000000}";
o.DatabaseConnectionStringResolver = id => db.GetConnectionString(id);
});
22. Resilience 弹性管道
Core 提供 AddResilienceCore() 注册 NoOp 管道(编译时占位),Polly 实现由 Galosys.Foundation.Polly.Core 提供。
services.AddCore(); // 内置 AddResilienceCore()(NoOp 默认)
services.AddPollyResilience(); // Polly 实现覆盖 NoOp(需引用 Polly.Core)
// 使用命名管道
var pipeline = provider.GetRequiredService<IResiliencePipelineProvider>()
.GetPipeline("my-service");
await pipeline.ExecuteAsync(async ct =>
{
return await httpClient.GetAsync("api/data", ct);
});
支持策略: Retry(重试)、CircuitBreaker(熔断)、Timeout(超时)、Bulkhead(隔离)、RateLimiter(限流)、Fallback(降级)。
{
"Resilience": {
"Pipelines": {
"my-service": {
"Retry": { "MaxRetryAttempts": 3, "BackoffType": "Exponential" },
"CircuitBreaker": { "FailureThreshold": 0.5, "SamplingDuration": "00:01:00" },
"Timeout": { "TimeoutInterval": "00:00:10" }
}
}
}
}
| 类 | 所在模块 | 说明 |
|---|---|---|
IResiliencePipeline |
Core | 弹性管道接口 |
IResiliencePipelineBuilder |
Core | 管道构建器(链式配置策略) |
IResiliencePipelineProvider |
Core | 命名管道提供者 |
NoOpResiliencePipeline |
Core | 默认 NoOp 实现(占位) |
PollyResiliencePipeline |
Polly.Core | Polly 真实实现 |
PollyResiliencePipelineBuilderFactory |
Polly.Core | 工厂模式解耦 |
模块职责分离:Core 只定义抽象 + NoOp;Polly 实现由
Galosys.Foundation.Polly.Core提供。下游模块通过AddPollyResilience()显式启用。
22. State Machine 状态机
Microsoft.Extensions.StateMachine — 三泛型 IStateMachine<S, E, C> 通用状态机,支持 Builder DSL、拦截器、监听器、持久化。
// 注册:三泛型 + 构建器 DSL + machineId
services.AddStateMachine<OrderState, OrderEvent, OrderContext>(builder =>
{
builder.ExternalTransition()
.From(OrderState.Pending).To(OrderState.Confirmed).On(OrderEvent.Submit)
.Perform((from, to, evt, ctx) => HandleSubmit(ctx));
builder.ExternalTransition()
.From(OrderState.Confirmed).To(OrderState.Shipped).On(OrderEvent.Ship)
.Perform((from, to, evt, ctx) => { });
builder.ExternalTransition()
.From(OrderState.Shipped).To(OrderState.Completed).On(OrderEvent.Deliver)
.Perform((from, to, evt, ctx) => { });
}, "order");
// 从工厂取实例(工厂惰性从 DI 解析,无需额外 Build 回填)
var factory = provider.GetRequiredService<IStateMachineFactory>();
var machine = factory.Get<OrderState, OrderEvent, OrderContext>("order");
// 触发转换(需指定源状态,返回 FireResult)
var result = await machine.FireAsync(OrderState.Pending, OrderEvent.Submit, context);
// result.Status: Accepted / NoTransition / Rejected / Error
// result.TargetState
| 类 | 说明 |
|---|---|
IStateMachine<S,E,C> |
状态机接口 |
IStateMachineFactory |
状态机工厂 |
IStateMachineInterceptor |
状态转换拦截器 |
IStateMachineListener |
状态转换监听器 |
IStateMachinePersister |
状态持久化(默认内存) |
23. Rules Engine 规则引擎
Microsoft.Extensions.Rules — 规则定义、构建、执行、事件监听与回退链。
// 注册
services.AddRules();
// 定义规则
[Rule(Name = "VipDiscount", Priority = 1)]
public class VipDiscountRule : IRuleEntity
{
public RuleExecuteResult Execute(RuleDefinition rule, object context)
{
var order = (OrderContext)context;
if (order.UserLevel == "VIP")
return RuleExecuteResult.Success(new { Discount = 0.9 });
return RuleExecuteResult.Skip();
}
}
// 执行
var engine = provider.GetRequiredService<IRuleEngine>();
var result = await engine.ExecuteAsync("order.discount", orderContext);
| 类 | 说明 |
|---|---|
IRuleEngine |
规则引擎接口 |
RuleBuilder |
规则构建器 |
RuleDefinition |
规则定义 |
FallbackChain |
参数回退链 |
IRuleEventListener |
规则事件监听器 |
24. Distributed Lock 分布式锁
Microsoft.Extensions.Locking.Distributed — 分布式锁抽象,内置内存实现。
// 注册
services.AddDistributedLock();
// 使用
var handle = await distributedLock.TryAcquireAsync("lock:order:123");
if (handle != null)
{
try { /* 临界区 */ }
finally { await handle.ReleaseAsync(); }
}
| 类 | 说明 |
|---|---|
IDistributedLock |
分布式锁接口 |
IDistributedLockHandle |
锁句柄 |
InMemoryDistributedLock |
内存实现(用于开发和测试) |
25. Distributed Idempotence 分布式幂等
Microsoft.Extensions.Idempotence — 分布式幂等性控制。
// 注册
services.AddIdempotence();
// 使用
var result = await idempotence.TryExecuteAsync("order:submit:123", async () =>
{
return await orderService.SubmitAsync(order);
});
| 类 | 说明 |
|---|---|
IDistributedIdempotence |
幂等性控制接口 |
InMemoryDistributedIdempotence |
内存实现 |
26. Alarming 告警
Microsoft.Extensions.Alarming — 告警日志基础设施。
// 注册
services.AddAlarmer();
// 使用
alarmer.Alarm("数据库连接超时", new { Db = "OrderDb", Timeout = 30 });
| 类 | 说明 |
|---|---|
IAlarmer |
告警器接口 |
Alarmer |
告警器抽象基类 |
AlarmLogger |
告警日志实现 |
27. AI 集成
Microsoft.Extensions.AI — 配置驱动的 AI 客户端 + RAG 能力。
27.1 注册
// 从 appsettings.json 读取 AI:Chat / AI:Embedding 配置
services.AddAI(configuration);
27.2 配置文件
"AI": {
"Chat": {
"Qwen": { "Provider": "OpenAI", "Endpoint": "", "ApiKey": "", "ModelId": "" },
"DeepSeek": { "Provider": "Anthropic", "Endpoint": "", "ApiKey": "", "ModelId": "" },
"Local": { "Provider": "Ollama", "Endpoint": "", "ApiKey": null, "ModelId": "" }
},
"Embedding": {
"Qwen": { "Provider": "Qwen", "Endpoint": "", "ApiKey": "", "ModelId": "" },
"OpenAI": { "Provider": "OpenAI", "Endpoint": "", "ApiKey": "", "ModelId": "" }
}
}
27.3 Chat 调用
// 通过 key 获取对应 ChatClient
var qwen = services.GetRequiredKeyedService<IChatClient>("Qwen");
// 每次调用可设置不同 SystemPrompt
var response = await qwen.GetResponseAsync(
[new(ChatRole.System, "你现在是一个英语翻译助手"),
new(ChatRole.User, "你好")]);
27.4 Embedding 调用
var gen = services.GetRequiredKeyedService<IEmbeddingGenerator<string, Embedding<float>>>("Qwen");
var embeddings = await gen.GenerateAsync(["文本1", "文本2"]);
27.5 RAG(检索增强生成)
使用 UseRag() 前需先注册 VectorStore 实现(如 InMemory、Qdrant 等):
// 注册 VectorStore(自行选择实现)
services.AddSingleton<VectorStore>(sp => new MyVectorStore(...));
// 通过管道注册全局 RAG
services.AddChatClient(builder => builder
.UseRag(configure: o => { o.Mode = RagMode.Simple; o.TopK = 3; })
.Use(new OpenAIClient(apiKey)).AsChatClient("gpt-4"));
// 调用时动态控制
var response = await chatClient.GetResponseAsync(
[new(ChatRole.User, "公司的年度目标是什么?")],
new ChatOptions
{
AdditionalProperties = new()
{
["rag_collection"] = "company_docs"
}
});
27.6 使用支持的 Chat Client
| Provider | 说明 | 实现方式 |
|---|---|---|
OpenAI(Chat+Embedding) |
OpenAI 兼容 API(含 Qwen/Azure) | meai.openai 官方包 |
Anthropic(Chat) |
Anthropic Claude | AnthropicClient SDK 包装 |
Ollama(Chat,扩展包) |
本地 Ollama | OllamaSharp |
Qwen(Embedding) |
通义千问 Embedding | 内置 QwenEmbeddingGenerator |
27.7 Chat 层中间件(护栏 / 压缩)
AddAI 为每个配置创建的 IChatClient 自动装配默认中间件管线,顺序为 UseOpenTelemetry → UseLogging → UseDistributedCache → UseCompaction → UseOutputGuardrail → [可选的 UseFunctionInvocation]。缺 DI 依赖(ILoggerFactory / IDistributedCache / 护栏 / 压缩服务)的中间件自动跳过。
开关位于 AIProviderOptions(Enable*,逐 provider 生效),默认值:EnableOpenTelemetry=true、EnableLogging=true、EnableDistributedCache=false(需应用注册 IDistributedCache)、EnableFunctionInvocation=false(防与 MAF agent 工具循环冲突)、EnableCompaction=true、EnableOutputGuardrail=true。
"AI": {
"Chat": {
"Qwen": { "Provider": "OpenAI", "Endpoint": "", "ApiKey": "", "ModelId": "",
"EnableDistributedCache": true }
}
}
也可在独立 IChatClient 上显式装配中间件(护栏/压缩原语位于 Microsoft.Extensions.AI 命名空间):
// 护栏:注册评估器链(TryAdd 语义,可覆盖)
services.AddOutputGuardrail(o => o.BlockedKeywords = ["机密"]);
// 压缩:注册选项
services.AddCompaction(o => o.MaxMessages = 32);
// 在 ChatClientBuilder 上显式挂载
services.AddChatClient(builder => builder
.UseCompaction(o => o.Strategy = CompactionStrategy.Truncate)
.UseOutputGuardrail(sp)
.Use(new OpenAIClient(apiKey)).AsChatClient("gpt-4"));
| 类型 | 说明 |
|---|---|
OutputGuardrailChatClient / UseOutputGuardrail |
输出护栏中间件,命中敏感词抛 OutputGuardrailException |
CompactionChatClient / UseCompaction / CompactionOptions |
对话压缩中间件,超限截断或摘要 |
AddOutputGuardrail / AddCompaction |
护栏 / 压缩 DI 注册 |
IOutputGuardrailEvaluator、RuleBasedOutputGuardrail、IPiiDetector、IPiiRedactor 等 |
护栏/PII 原语(自 Galosys.Foundation.Agents.AI 下沉,无 MAF 依赖) |
28. Excel 操作
IXlsHelper — 流式读取、流式写入、模板填充,支持列映射和自定义转换。
// 注册
services.AddXlsHelper();
// 流式读取
var records = xlsHelper.ExtractAsync<OrderDto>(stream, options);
// 流式写入
await xlsHelper.WriteAsync(stream, orders, options);
// 模板填充
await xlsHelper.FillAsync(templateStream, outputStream, data, options);
| 类 | 说明 |
|---|---|
IXlsHelper |
Excel 操作接口 |
IXlsWriter<T> |
流式写入器 |
IXlsSheetWriter<T> |
工作表写入器 |
XlsColumnAttribute |
列映射特性 |
XlsSheetAttribute |
工作表映射特性 |
AbstractXlsAppService |
Excel 应用服务基类 |
29. Responsibility Chain 责任链
public class ValidationHandler : AbstractChainHandler<OrderContext>
{
public override async Task HandleAsync(OrderContext context, Func<Task> next)
{
if (context.IsValid)
await next();
}
}
// 执行
await chainClient.ExecuteAsync(context);
30. 数据结构
BloomFilter
var filter = new BloomFilter<string>(expectedItems: 100000, falsePositiveRate: 0.01);
filter.Add("item1");
bool exists = filter.Contains("item1"); // true
WorkerPool
// 注册
services.AddWorkerPool();
// 使用
await workerPool.EnqueueAsync(async ct => { /* 工作任务 */ }, cancellationToken);
| 实现 | 说明 |
|---|---|
TaskWorkerPool |
基于 Task 的工作池 |
ThreadWorkerPool |
基于 Thread 的工作池 |
ChannelTemplate
var channel = new ChannelTemplate<string>(capacity: 100);
await channel.Writer.WriteAsync("data");
var item = await channel.Reader.ReadAsync();
31. 工具类
Env — 环境检测
Env.IsKubernetes; // 是否在 K8s 中运行
Env.MachineIP; // 本机 IP 地址
Env.MachineName; // 主机名
Env.IsDevelopment(); // 是否开发环境
ServiceLocator — 服务定位器
var service = ServiceLocator.GetService<IMyService>();
Poco — DTO 基类
public class UserDto : Poco
{
public string Name { get; set; }
}
var clone = original.Clone();
ITreeNode — 树形结构
var tree = TreeNodeHelper.BuildTree(nodes);
var flat = TreeNodeHelper.Flatten(tree);
ITimeProvider — 时间提供者
public class MyService
{
public MyService(ITimeProvider time) { }
// 测试时可注入 mock 时间
}
数据脱敏
public class UserDto
{
[DataMask(MaskType.Partial)]
public string Phone { get; set; } // 138****1234
}
API 签名
var signature = SignUtils.GenerateSign(parameters, secretKey);
var valid = SignUtils.VerifySign(parameters, secretKey, signature);
二倍均值算法(红包分配)
var amounts = Bma.Divide(totalAmount: 100, count: 5);
命名帮助
var queue = Naming.Queue("order"); // 队列命名
var topic = Naming.Topic("order"); // 主题命名
var key = Naming.Key("order:123"); // Key 命名
Enumeration — 智能枚举
public class OrderStatus : Enumeration<OrderStatus>
{
public static readonly OrderStatus Pending = new(1, "待处理");
public static readonly OrderStatus Completed = new(2, "已完成");
}
32. DI 服务注册
// 核心注册(模块化、消息总线、消息发布等)
// 幂等:模块路径(UseModularization)与显式路径共存时不重复注册
services.AddCore();
// COLA 架构
services.AddCola(typeof(MyCommand).Assembly);
// CQRS Lite(一行扫描所有 ICommandHandler<,> 注册 + Dispatcher Singleton)
// 零参默认走 DependencyContext.Default.GetImplementTypes()(与框架其余扫描器一致:
// 拓扑排序后从 AppContext.BaseDirectory 加载运行时 DLL,自动排除测试 SDK 程序集并全局缓存)
services.AddCqrs();
// 或显式传程序集(xUnit test host / AOT / 限定扫描范围场景推荐)
services.AddCqrs(typeof(MyCommand).Assembly);
// 消息总线 + Outbox
services.AddMessageBus();
services.AddOutbox();
// 弹性管道(NoOp 默认)
services.AddResilienceCore();
// 若需 Polly 实现:services.AddPollyResilience();
// 状态机
services.AddStateMachine();
// 规则引擎
services.AddRules();
// 分布式锁
services.AddDistributedLock();
// 分布式幂等
services.AddIdempotence();
// 告警
services.AddAlarmer();
// Excel 操作
services.AddXlsHelper();
// AI 集成(读取 appsettings.json 的 AI 节)
services.AddAI(configuration);
// 服务发现
services.AddServiceDiscovery();
// 健康检查(自动发现 [HealthCheck] 属性探针 + 内置 ResourceUtilization/Lifecycle)
services.AddHealthChecksAll();
// 自动扫描注册
// 排除依赖测试 SDK(xunit/NUnit/MSTest 等)的程序集,宿主与集成包照常扫描
services.AddScannable();
33. 目录结构
Galosys.Foundation.Core/
├── Galosys\Foundation\Core\
│ ├── ModuleDescriptor.cs
│ ├── Executor/ # COLA Executor 模板方法
│ ├── ExtensionPoint/ # COLA ExtensionPoint 扩展点
│ └── Xls/ # Excel 操作
├── Microsoft\Extensions\
│ ├── AI/ # AI 集成(通义千问)
│ ├── Alarming/ # 告警基础设施
│ ├── Configuration/ # 配置绑定扩展
│ ├── DependencyInjection/ # DI 注册 + 模块化系统
│ ├── Diagnostics/ # 诊断 + Metrics
│ ├── Hosting/ # HostBuilder 扩展
│ ├── Idempotence/ # 分布式幂等
│ ├── Locking/Distributed/ # 分布式锁
│ ├── Messaging/ # CQRS Lite Behaviors(Phase 2+ 占位;契约已迁入 Galosys/Foundation/Core/)
│ ├── MessageBus/ # 消息总线 + Outbox 引擎 (renamed from Messaging)
│ ├── Options/ # 配置选项类
│ ├── Resilience/ # 弹性管道
│ ├── Rules/ # 规则引擎
│ ├── StateMachine/ # 状态机
│ └── MessageBus/ # 消息总线
├── System\
│ ├── BloomFilter.cs # 布隆过滤器
│ ├── ChannelTemplate.cs # Channel 消息管道模板
│ ├── DateTimeExtensions.cs
│ ├── Env.cs # 环境检测
│ ├── Enumeration.cs # 智能枚举
│ ├── Naming.cs # 命名帮助
│ ├── Poco.cs # DTO 基类
│ ├── ServiceLocator.cs # 服务定位器
│ ├── Security/Cryptography/ # 加密算法
│ ├── StringExtensions.cs
│ └── WorkerPool/ # 工作池
└── System\Text\Json\Serialization\
└── DataMaskConverter.cs # 数据脱敏
34. 测试
Outbox 测试覆盖
| 测试文件 | 组件 | 用例数 |
|---|---|---|
InMemoryOutboxStoreTests |
InMemoryOutboxStore | 14 |
OutboxRelayTests |
OutboxRelay 后台轮询 | 6 |
MessageBusOutboxTests |
MessageBus outbox 路径 | 4 |
PendingMsgColTests |
PendingMsgCol AsyncLocal 收集器 | 3 |
# 运行 outbox 存储层测试
dotnet test framework/test/Galosys.Foundation.Core.Tests/ --filter "FullyQualifiedName~InMemoryOutboxStoreTests"
# 运行 outbox 服务层测试
dotnet test framework/test/Galosys.Foundation.Core.Tests/ --filter "FullyQualifiedName~OutboxRelay"
dotnet test framework/test/Galosys.Foundation.Core.Tests/ --filter "FullyQualifiedName~MessageBusOutbox"
35. 依赖
- Microsoft.Extensions.Caching.Abstractions / Memory
- Microsoft.Extensions.DependencyInjection
- Microsoft.Extensions.DependencyModel
- Microsoft.Extensions.Diagnostics.HealthChecks
- Microsoft.Extensions.Hosting
- Microsoft.Extensions.Http
- Microsoft.Extensions.ObjectPool
- Polly.Core
- System.Threading.RateLimiting
Outbox 引擎零新增依赖,复用已有 Microsoft.Extensions.Hosting / DI。
| 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
- Microsoft.Extensions.AI (>= 10.7.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.7.0)
- Microsoft.Extensions.AI.OpenAI (>= 10.7.0)
- microsoft.extensions.caching.abstractions (>= 10.0.9)
- microsoft.extensions.caching.hybrid (>= 10.0.0)
- microsoft.extensions.caching.memory (>= 10.0.0)
- microsoft.extensions.compliance.redaction (>= 10.0.0)
- microsoft.extensions.dependencyinjection (>= 10.0.0)
- microsoft.extensions.dependencymodel (>= 10.0.0)
- microsoft.extensions.diagnostics.healthchecks (>= 10.0.10)
- microsoft.extensions.diagnostics.healthchecks.common (>= 10.0.0)
- microsoft.extensions.diagnostics.healthchecks.resourceutilization (>= 10.1.0)
- microsoft.extensions.hosting (>= 10.0.0)
- microsoft.extensions.http (>= 10.0.0)
- microsoft.extensions.objectpool (>= 10.0.1)
- microsoft.extensions.servicediscovery (>= 10.0.0)
- Microsoft.Extensions.Validation (>= 10.0.11)
- Microsoft.Extensions.VectorData.Abstractions (>= 10.7.0)
- system.threading.ratelimiting (>= 10.0.9)
NuGet packages (144)
Showing the top 5 NuGet packages that depend on Galosys.Foundation.Core:
| Package | Downloads |
|---|---|
|
Galosys.Foundation.AspNetCore
Galosys.Foundation快速开发库 |
|
|
Galosys.Foundation.Data
Galosys.Foundation快速开发库 |
|
|
Galosys.Foundation.AspNetCore.DynamicApi
Galosys.Foundation快速开发库 |
|
|
Galosys.Foundation.Actuator
Galosys.Foundation快速开发库 |
|
|
Galosys.Foundation.HttpClient
Galosys.Foundation快速开发库 |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 26.9.10.1 | 0 | 9/10/2026 |
| 26.9.3.1 | 823 | 9/3/2026 |
| 26.8.29.1 | 1,408 | 8/31/2026 |
| 26.8.26.1 | 1,470 | 8/26/2026 |
| 26.8.23.1 | 1,881 | 8/23/2026 |
| 26.8.21.1 | 2,029 | 8/21/2026 |
| 26.8.20.1 | 2,075 | 8/20/2026 |
| 26.8.18.1 | 1,629 | 8/18/2026 |
| 26.8.17.1 | 1,630 | 8/17/2026 |
| 26.8.13.2 | 1,398 | 8/13/2026 |
| 26.8.13.1 | 1,393 | 8/13/2026 |
| 26.8.12.2 | 1,361 | 8/12/2026 |
| 26.8.12.1 | 1,369 | 8/12/2026 |
| 26.8.10.1 | 1,396 | 8/10/2026 |
| 26.8.5.1 | 1,570 | 8/5/2026 |
| 26.8.4.1 | 1,618 | 8/4/2026 |
| 26.8.3.1 | 1,676 | 8/3/2026 |
| 26.7.31.1 | 1,642 | 7/31/2026 |
| 26.7.30.1 | 1,531 | 7/30/2026 |
| 26.7.29.1 | 1,556 | 7/29/2026 |