Skip to content

Commit df989a7

Browse files
committed
docs: document new framework infrastructure primitives
Update api.md (EN+ZH) and architecture.md (EN+ZH) to cover: - Async service registration (AddModuleAsync, AddModularApplicationAsync) - IConfiguration on ServiceConfigurationContext - IModuleLifecycleContributor and ModuleLifecycleOptions - ObjectAccessor<T>, PreConfigureActionList<T>, PreConfigure<T>() - Conventional DI registration markers and AddConventionalServices()
1 parent f8926ce commit df989a7

4 files changed

Lines changed: 40 additions & 6 deletions

File tree

docs/guide/architecture.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Each logical class maps to a dedicated abstract base class. Production modules m
8282

8383
`ModuleBase` remains the low-level engine primitive. Direct `ModuleBase` inheritance is reserved for low-level modularity infrastructure only. All other modules should choose one of the four category-specific bases.
8484

85-
The service-registration entry point is shared: every module receives a `ServiceConfigurationContext` that wraps `IServiceCollection` along with an `IInitLoggerFactory` for pre-DI logging and an `Items` dictionary for cross-module state. `ModuleBase` provides `Configure<TOptions>()` helpers and owns the shared lifecycle template: `OnLoaded`, `PreConfigureServices`, `ConfigureServices`, `PostConfigureServices`, `PreInitializeAsync`, `InitializeAsync`, `PostInitializeAsync`, and `ShutdownAsync`. During module initialization, any log entries buffered through `IInitLogger<T>` during the service-registration phase are replayed through the real `ILoggerFactory`.
85+
The service-registration entry point is shared: every module receives a `ServiceConfigurationContext` that wraps `IServiceCollection` along with an `IInitLoggerFactory` for pre-DI logging, an optional `IConfiguration` when the host has registered one, and an `Items` dictionary for cross-module state. `ModuleBase` provides `Configure<TOptions>()` and `PreConfigure<TOptions>()` helpers and owns the shared lifecycle template: `OnLoaded`, `PreConfigureServices`, `ConfigureServices`, `PostConfigureServices`, `PreInitializeAsync`, `InitializeAsync`, `PostInitializeAsync`, and `ShutdownAsync`. Async service registration alternatives (`PreConfigureServicesAsync`, `ConfigureServicesAsync`, `PostConfigureServicesAsync`) are available for modules that need to perform I/O during registration. During module initialization, any log entries buffered through `IInitLogger<T>` during the service-registration phase are replayed through the real `ILoggerFactory`. Lifecycle contributors registered via `ModuleLifecycleOptions` run cross-cutting logic around every module's initialization and shutdown phases.
8686

8787
During `OnLoaded`, `ModuleBase` caches the current module descriptor, direct dependencies, direct dependents, resolved category, and root-module state. Category-specific base classes should use this cached topology instead of querying the catalog again.
8888

@@ -201,7 +201,7 @@ The rule is simple:
201201
| Module | Owns | Must Not Own | Depends On |
202202
|---|---|---|---|
203203
| `ChengYuan.Core` | Base exceptions, error codes, `Result`, DDD primitives, strongly typed IDs, object extension contracts, `IClock`, `IGuidGenerator` | Json, EF Core, tenant context, current user context, caching, outbox | Nothing internal |
204-
| `ChengYuan.Core.Runtime` | Module descriptors, module catalog, lifecycle hooks, module bootstrap and ordering, `ServiceConfigurationContext`, init logging (`IInitLoggerFactory`, `IInitLogger<T>`), logging utilities (`IHasLogLevel`, `IExceptionWithSelfLogging`) | Domain primitives, serializer providers, data providers | `ChengYuan.Core` |
204+
| `ChengYuan.Core.Runtime` | Module descriptors, module catalog, lifecycle hooks, module bootstrap and ordering, `ServiceConfigurationContext`, init logging (`IInitLoggerFactory`, `IInitLogger<T>`), logging utilities (`IHasLogLevel`, `IExceptionWithSelfLogging`), async service registration (`AddModuleAsync`, `AddModularApplicationAsync`), lifecycle contributors (`IModuleLifecycleContributor`, `ModuleLifecycleOptions`), dependency injection primitives (`ObjectAccessor<T>`, `PreConfigureActionList<T>`, conventional registration markers) | Domain primitives, serializer providers, data providers | `ChengYuan.Core` |
205205
| `ChengYuan.Core.Json` | Serializer abstractions, System.Text.Json integration, strongly typed ID converters | EF Core, repository or UoW logic | `ChengYuan.Core` |
206206
| `ChengYuan.Core.Validation` | Validation contracts and default validation pipeline | Localization resources, persistence providers | `ChengYuan.Core` |
207207
| `ChengYuan.Core.Localization` | Resource registration and exception or error localization seams | Validation runtime policy, persistence providers | `ChengYuan.Core` |

docs/reference/api.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,30 @@ Core module composition primitives.
5050
| `DependsOnAttribute` | Declares direct module dependencies for composition ordering. |
5151
| `ModuleCatalog` | Exposes the ordered module list loaded by a host. |
5252
| `IModuleDescriptor.Category` | Reports whether a loaded module is `FrameworkCore`, `Application`, `Extension`, or `Host`. |
53-
| `ServiceConfigurationContext` | Service-registration context wrapping `IServiceCollection`, `IInitLoggerFactory`, and a cross-module `Items` dictionary. Passed to every module during `ConfigureServices`. |
53+
| `ServiceConfigurationContext` | Service-registration context wrapping `IServiceCollection`, `IInitLoggerFactory`, an optional `IConfiguration`, and a cross-module `Items` dictionary. Passed to every module during `ConfigureServices`. |
5454
| `IInitLoggerFactory` | Factory for creating `IInitLogger<T>` instances that buffer log entries before DI is built. Exposed via `ServiceConfigurationContext.InitLoggerFactory`. |
5555
| `IInitLogger<T>` | `ILogger<T>` implementation that buffers `InitLogEntry` records during module loading for later replay once DI is available. |
5656
| `InitLogEntry` | Sealed record carrying category name, log level, event id, formatted message, and optional exception for replay. |
5757
| `IHasLogLevel` | Interface for exceptions or objects that carry a self-declared `LogLevel`. |
5858
| `IExceptionWithSelfLogging` | Interface for exceptions that provide structured self-logging via `Log(ILogger)`. |
5959
| `HasLogLevelExtensions` | Fluent `WithLogLevel()` extension for `IHasLogLevel` exceptions. |
60+
| `AddModuleAsync<TModule>()` | Async alternative to `AddModule<TModule>()` that calls `PreConfigureServicesAsync`, `ConfigureServicesAsync`, and `PostConfigureServicesAsync` on each module. |
61+
| `AddModularApplicationAsync<TStartupModule>()` | Async alternative to `AddModularApplication<TStartupModule>()` for hosts that need async service registration. |
62+
| `IModuleLifecycleContributor` | Extension point for cross-cutting logic that runs during every module's `InitializeAsync` and `ShutdownAsync`. Contributors are invoked in registration order on init and reverse order on shutdown. |
63+
| `ModuleLifecycleOptions` | Options class carrying an ordered `Contributors` list of `IModuleLifecycleContributor` types resolved at initialization time. |
64+
| `IObjectAccessor<T>` | Covariant read-only accessor for a mutable value stored in the service collection during registration. |
65+
| `ObjectAccessor<T>` | Mutable implementation of `IObjectAccessor<T>`, registered at position 0 in `IServiceCollection` for fast retrieval. |
66+
| `AddObjectAccessor<T>()` | Registers an `ObjectAccessor<T>` into the service collection. Throws if a duplicate is added. |
67+
| `TryAddObjectAccessor<T>()` | Registers an `ObjectAccessor<T>` only if one does not already exist. |
68+
| `GetObject<T>()` / `GetObjectOrNull<T>()` | Retrieves the value from a registered `ObjectAccessor<T>`. |
69+
| `PreConfigureActionList<T>` | Accumulator for pre-configuration actions. Modules call `PreConfigure<T>(action)` to contribute, and the framework applies all actions before `ConfigureServices`. |
70+
| `PreConfigure<T>(Action<T>)` | Extension on `IServiceCollection` to register a pre-configuration action for an options type. |
71+
| `ExecutePreConfiguredActions<T>()` | Applies all accumulated `PreConfigure<T>` actions and returns the configured options instance. |
72+
| `ITransientService` | Marker interface for classes that should be registered as transient by `AddConventionalServices()`. |
73+
| `IScopedService` | Marker interface for classes that should be registered as scoped by `AddConventionalServices()`. |
74+
| `ISingletonService` | Marker interface for classes that should be registered as singleton by `AddConventionalServices()`. |
75+
| `DisableConventionalRegistrationAttribute` | Attribute that opts a class out of conventional service registration scanning. |
76+
| `AddConventionalServices(Assembly)` | Scans an assembly for classes implementing `ITransientService`, `IScopedService`, or `ISingletonService` and registers them with matching service types using `TryAdd` semantics. |
6077

6178
### `ChengYuan.Core.Json`
6279

docs/zh-cn/guide/architecture.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ src/
8282

8383
`ModuleBase` 仍然保留为底层模块引擎原语。只有低层模块化基础设施代码才允许直接继承它。其他生产模块都应使用四个分类基类之一。
8484

85-
服务注册入口保持统一:所有模块都接收一个 `ServiceConfigurationContext`,包裹了 `IServiceCollection`、用于 DI 构建前日志记录的 `IInitLoggerFactory`、以及跨模块传递状态的 `Items` 字典。`ModuleBase` 提供 `Configure<TOptions>()` 系列辅助方法,并承载统一生命周期模板:`OnLoaded``PreConfigureServices``ConfigureServices``PostConfigureServices``PreInitializeAsync``InitializeAsync``PostInitializeAsync``ShutdownAsync`。模块初始化时,注册阶段通过 `IInitLogger<T>` 缓冲的日志条目会通过真实的 `ILoggerFactory` 重放。
85+
服务注册入口保持统一:所有模块都接收一个 `ServiceConfigurationContext`,包裹了 `IServiceCollection`、用于 DI 构建前日志记录的 `IInitLoggerFactory`寿主已注册时可用的可选 `IConfiguration`以及跨模块传递状态的 `Items` 字典。`ModuleBase` 提供 `Configure<TOptions>()` `PreConfigure<TOptions>()` 系列辅助方法,并承载统一生命周期模板:`OnLoaded``PreConfigureServices``ConfigureServices``PostConfigureServices``PreInitializeAsync``InitializeAsync``PostInitializeAsync``ShutdownAsync`异步服务注册替代方法(`PreConfigureServicesAsync``ConfigureServicesAsync``PostConfigureServicesAsync`)供需要在注册阶段执行 I/O 的模块使用。模块初始化时,注册阶段通过 `IInitLogger<T>` 缓冲的日志条目会通过真实的 `ILoggerFactory` 重放。通过 `ModuleLifecycleOptions` 注册的生命周期贡献者会在每个模块的初始化和关闭阶段执行横切逻辑
8686

8787
`OnLoaded` 阶段,`ModuleBase` 会缓存当前模块描述、直接依赖、直接被依赖方、分类结果以及是否为 root module。分类基类应直接使用这些缓存拓扑信息,而不是再次回查 catalog。
8888

@@ -175,7 +175,7 @@ src/
175175
| 模块 | 负责内容 | 明确不负责 | 依赖 |
176176
|---|---|---|---|
177177
| `ChengYuan.Core` | 基础异常、错误码、`Result`、DDD 原语、强类型 Id、对象扩展契约、`IClock``IGuidGenerator` | Json、EF Core、租户上下文、当前用户上下文、缓存、Outbox | 不依赖内部模块 |
178-
| `ChengYuan.Core.Runtime` | 模块描述、模块目录、生命周期钩子、模块引导与排序、`ServiceConfigurationContext`、初始化日志(`IInitLoggerFactory``IInitLogger<T>`)、日志工具(`IHasLogLevel``IExceptionWithSelfLogging`| 领域原语、序列化 Provider、数据 Provider | `ChengYuan.Core` |
178+
| `ChengYuan.Core.Runtime` | 模块描述、模块目录、生命周期钩子、模块引导与排序、`ServiceConfigurationContext`、初始化日志(`IInitLoggerFactory``IInitLogger<T>`)、日志工具(`IHasLogLevel``IExceptionWithSelfLogging`、异步服务注册(`AddModuleAsync``AddModularApplicationAsync`)、生命周期贡献者(`IModuleLifecycleContributor``ModuleLifecycleOptions`)、依赖注入原语(`ObjectAccessor<T>``PreConfigureActionList<T>`、约定式注册标记) | 领域原语、序列化 Provider、数据 Provider | `ChengYuan.Core` |
179179
| `ChengYuan.Core.Json` | 序列化抽象、System.Text.Json 集成、强类型 Id 转换器 | EF Core、仓储或 UoW 逻辑 | `ChengYuan.Core` |
180180
| `ChengYuan.Core.Validation` | 校验契约与默认校验管道 | 本地化资源、持久化 Provider | `ChengYuan.Core` |
181181
| `ChengYuan.Core.Localization` | 资源注册与异常/错误消息本地化缝隙 | 校验运行时策略、持久化 Provider | `ChengYuan.Core` |

docs/zh-cn/reference/api.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,30 @@
5050
| `DependsOnAttribute` | 声明直接模块依赖,用于组合排序。 |
5151
| `ModuleCatalog` | 暴露 Host 已加载的有序模块列表。 |
5252
| `IModuleDescriptor.Category` | 报告已加载模块属于 `FrameworkCore``Application``Extension` 还是 `Host`|
53-
| `ServiceConfigurationContext` | 服务注册上下文,包装 `IServiceCollection``IInitLoggerFactory` 与跨模块 `Items` 字典。在 `ConfigureServices` 阶段传递给每个模块。 |
53+
| `ServiceConfigurationContext` | 服务注册上下文,包装 `IServiceCollection``IInitLoggerFactory`、可选的 `IConfiguration` 与跨模块 `Items` 字典。在 `ConfigureServices` 阶段传递给每个模块。 |
5454
| `IInitLoggerFactory` | 用于创建 `IInitLogger<T>` 实例的工厂,在 DI 容器构建前缓冲日志条目。通过 `ServiceConfigurationContext.InitLoggerFactory` 暴露。 |
5555
| `IInitLogger<T>` | 在模块加载期间缓冲 `InitLogEntry` 记录的 `ILogger<T>` 实现,待 DI 可用后重放。 |
5656
| `InitLogEntry` | 密封记录,携带类别名、日志级别、事件 Id、格式化消息与可选异常,用于延迟重放。 |
5757
| `IHasLogLevel` | 为异常或对象声明自带 `LogLevel` 的接口。 |
5858
| `IExceptionWithSelfLogging` | 通过 `Log(ILogger)` 提供结构化自记录能力的异常接口。 |
5959
| `HasLogLevelExtensions` | 面向 `IHasLogLevel` 异常的 fluent `WithLogLevel()` 扩展方法。 |
60+
| `AddModuleAsync<TModule>()` | `AddModule<TModule>()` 的异步替代,依次调用每个模块的 `PreConfigureServicesAsync``ConfigureServicesAsync``PostConfigureServicesAsync`|
61+
| `AddModularApplicationAsync<TStartupModule>()` | `AddModularApplication<TStartupModule>()` 的异步替代,供需要异步服务注册的宿主使用。 |
62+
| `IModuleLifecycleContributor` | 横切扩展点,在每个模块的 `InitializeAsync``ShutdownAsync` 期间执行。初始化时按注册顺序调用,关闭时按逆序调用。 |
63+
| `ModuleLifecycleOptions` | 携带有序 `Contributors` 列表的选项类,包含在初始化时解析的 `IModuleLifecycleContributor` 类型集合。 |
64+
| `IObjectAccessor<T>` | 协变只读访问器,用于读取服务注册阶段存入 `IServiceCollection` 的可变值。 |
65+
| `ObjectAccessor<T>` | `IObjectAccessor<T>` 的可变实现,注册在 `IServiceCollection` 的位置 0 以实现快速检索。 |
66+
| `AddObjectAccessor<T>()` | 向服务集合注册 `ObjectAccessor<T>`。重复添加时抛出异常。 |
67+
| `TryAddObjectAccessor<T>()` | 仅在不存在时才注册 `ObjectAccessor<T>`|
68+
| `GetObject<T>()` / `GetObjectOrNull<T>()` | 从已注册的 `ObjectAccessor<T>` 中检索值。 |
69+
| `PreConfigureActionList<T>` | 预配置操作累加器。模块调用 `PreConfigure<T>(action)` 贡献操作,框架在 `ConfigureServices` 之前统一应用。 |
70+
| `PreConfigure<T>(Action<T>)` | `IServiceCollection` 上的扩展方法,用于注册选项类型的预配置动作。 |
71+
| `ExecutePreConfiguredActions<T>()` | 将已累积的所有 `PreConfigure<T>` 动作应用到选项实例并返回。 |
72+
| `ITransientService` |`AddConventionalServices()` 按 Transient 生命周期注册的标记接口。 |
73+
| `IScopedService` |`AddConventionalServices()` 按 Scoped 生命周期注册的标记接口。 |
74+
| `ISingletonService` |`AddConventionalServices()` 按 Singleton 生命周期注册的标记接口。 |
75+
| `DisableConventionalRegistrationAttribute` | 将类排除在约定式服务注册扫描之外的特性标记。 |
76+
| `AddConventionalServices(Assembly)` | 扫描程序集中实现 `ITransientService``IScopedService``ISingletonService` 的类,并使用 `TryAdd` 语义按匹配的服务类型注册。 |
6077

6178
### `ChengYuan.Core.Json`
6279

0 commit comments

Comments
 (0)