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
                    
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="Galosys.Foundation.Core" Version="26.9.10.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Galosys.Foundation.Core" Version="26.9.10.1" />
                    
Directory.Packages.props
<PackageReference Include="Galosys.Foundation.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 Galosys.Foundation.Core --version 26.9.10.1
                    
#r "nuget: Galosys.Foundation.Core, 26.9.10.1"
                    
#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 Galosys.Foundation.Core@26.9.10.1
                    
#: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=Galosys.Foundation.Core&version=26.9.10.1
                    
Install as a Cake Addin
#tool nuget:?package=Galosys.Foundation.Core&version=26.9.10.1
                    
Install as a Cake Tool

Galosys.Foundation.Core

成熟度: 🟢 稳定 — 生产可用,测试充分,活跃维护

Galosys.Foundation 核心库,提供统一响应模型、DDD 实体基类、扩展方法、安全加密、消息总线、模块化机制等基础能力。

特性一览

领域 功能
统一响应 UnifiedResponse 成功/失败/异常/处理中
DDD 实体 Entity / FullEntity / TenantEntity / AppEntity + 领域事件
ID 生成 Snowflake、LocalGenerator、Nanoid、Ulid、Uuid
分页 PageOutputPageQuery 分页查询基类
消息 事件订阅/发布、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 = 命令 FullNamecqrs.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 ErrorsIReadOnlyList<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 改为 TryAcquireBatchParallel.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)

框架内置 ITenantContextIAppContextIUserContext 三个 Singleton 上下文服务,基于 AsyncLocal<T> 实现请求级隔离。

public class MyService
{
    public MyService(ITenantContext tenant, IAppContext app, IUserContext user) { }
}

21. 多租户(Multi-Tenancy)

框架提供多层防御的多租户体系:行级隔离 + fail-secure 默认 + 显式系统模式 + 表级与插入级穿透。设计依据 ADR-0004ADR-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 = nullTableName = "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 / ConnectionStringITenantContext.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 自动装配默认中间件管线,顺序为 UseOpenTelemetryUseLoggingUseDistributedCacheUseCompactionUseOutputGuardrail → [可选的 UseFunctionInvocation]。缺 DI 依赖(ILoggerFactory / IDistributedCache / 护栏 / 压缩服务)的中间件自动跳过。

开关位于 AIProviderOptionsEnable*,逐 provider 生效),默认值:EnableOpenTelemetry=trueEnableLogging=trueEnableDistributedCache=false(需应用注册 IDistributedCache)、EnableFunctionInvocation=false(防与 MAF agent 工具循环冲突)、EnableCompaction=trueEnableOutputGuardrail=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 注册
IOutputGuardrailEvaluatorRuleBasedOutputGuardrailIPiiDetectorIPiiRedactor 护栏/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 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 (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
Loading failed