Table of Contents

模块系统

契约

public interface IModule
{
    void ConfigureServices(IServiceCollection services) { }                 // 注册阶段(容器 Build 前)
    Task OnInitializedAsync(ModuleContext ctx, CancellationToken ct = default); // 初始化(按拓扑序)
    Task OnShutdownAsync(ModuleContext ctx, CancellationToken ct = default);    // 关闭(逆序)
}

三个钩子全部可选。

依赖声明

[DependsOn(typeof(DataModule))]
public class UserModule : IModule;

框架构建依赖图并拓扑排序:被依赖者先注册、先初始化、后关闭。循环依赖启动即失败(报错带 A -> B -> A 路径)。

生命周期

发现程序集 → 约定注入 → ConfigureServices(拓扑序)
  → host.StartAsync → [基础设施前置任务] → OnInitializedAsync(拓扑序)→ 队列/调度器启动
  → 运行期:事件 / 队列 / 缓存 / 链路指标
  → host.StopAsync → OnShutdownAsync(逆序)

初始化失败时已初始化模块逆序回滚,原始异常原样抛出。

模块间解耦:事件

public record UserCreated(string Name);

public class WelcomeEmailSender : IEventHandler<UserCreated>
{
    public Task HandleAsync(UserCreated e, CancellationToken ct = default) { /* ... */ }
}
await context.Events.PublishAsync(new UserCreated("alice"));

处理器自动发现注入,发布方编译期不需要知道谁在处理。跨进程/要求可靠投递时改用发件箱。

自定义链路

using var span = ctx.StartActivity("加载配置");   // 挂入框架链路树

并行初始化(可选)

模块多、初始化含 IO 等待时,同一依赖层(互不依赖)的模块可并发初始化:

builder.Services.AddLedon(o => o.ParallelInitialization = true);
  • 层与层之间仍保持拓扑序(被依赖者先初始化),只有同层并行;
  • 同层模块的初始化顺序不再确定(日志/诊断顺序会变)——模块间有隐式依赖时用 [DependsOn] 显式声明;
  • 失败回滚语义不变:已初始化的模块(含并行层中已完成的)按逆序关闭,原始异常原样抛出。