You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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()
Copy file name to clipboardExpand all lines: docs/guide/architecture.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,7 +82,7 @@ Each logical class maps to a dedicated abstract base class. Production modules m
82
82
83
83
`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.
84
84
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.
86
86
87
87
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.
88
88
@@ -201,7 +201,7 @@ The rule is simple:
201
201
| Module | Owns | Must Not Own | Depends On |
202
202
|---|---|---|---|
203
203
|`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 |
|`DependsOnAttribute`| Declares direct module dependencies for composition ordering. |
51
51
|`ModuleCatalog`| Exposes the ordered module list loaded by a host. |
52
52
|`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`. |
54
54
|`IInitLoggerFactory`| Factory for creating `IInitLogger<T>` instances that buffer log entries before DI is built. Exposed via `ServiceConfigurationContext.InitLoggerFactory`. |
55
55
|`IInitLogger<T>`|`ILogger<T>` implementation that buffers `InitLogEntry` records during module loading for later replay once DI is available. |
56
56
|`InitLogEntry`| Sealed record carrying category name, log level, event id, formatted message, and optional exception for replay. |
57
57
|`IHasLogLevel`| Interface for exceptions or objects that carry a self-declared `LogLevel`. |
58
58
|`IExceptionWithSelfLogging`| Interface for exceptions that provide structured self-logging via `Log(ILogger)`. |
59
59
|`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. |
0 commit comments