init
This commit is contained in:
68
enriched-partialglm/Common/DTS.Common.Core/ServiceManager.md
Normal file
68
enriched-partialglm/Common/DTS.Common.Core/ServiceManager.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Core/ServiceManager/IServicePublishedEvent.cs
|
||||
- Common/DTS.Common.Core/ServiceManager/ServicePublishedEvent.cs
|
||||
- Common/DTS.Common.Core/ServiceManager/ServiceManager.cs
|
||||
generated_at: "2026-04-16T11:43:09.898125+00:00"
|
||||
model: "zai-org/GLM-5-FP8"
|
||||
schema_version: 1
|
||||
sha256: "a01f75e5b963dd9f"
|
||||
---
|
||||
|
||||
# Documentation: DTS.Common.Core.ServiceManager
|
||||
|
||||
## 1. Purpose
|
||||
This module implements a service locator pattern via a static `ServiceManager` class. It allows components to publish implementations of interfaces (services) into a global container and retrieve them elsewhere without direct coupling to the implementation. It acts as a runtime registry for singleton services, supporting publication, retrieval, existence checks, and un-publication, while broadcasting state changes via an event system.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `IServicePublishedEvent` (Interface)
|
||||
Defines the contract for events fired when a service state changes.
|
||||
* `Type ServiceType { get; }` — Gets the type of the service being published or unpublished.
|
||||
* `bool IsPublished { get; }` — Returns `true` if the service is being published; `false` if it is being unpublished.
|
||||
|
||||
### `ServicePublishedEvent` (Class)
|
||||
Concrete implementation of `IServicePublishedEvent`.
|
||||
* `Type ServiceType { get; internal set; }` — The service type. The setter is `internal`.
|
||||
* `bool IsPublished { get; internal set; }` — The publication state. The setter is `internal`.
|
||||
|
||||
### `ServiceManager` (Static Class)
|
||||
The static gateway for managing service registration.
|
||||
* `public static void Publish(T item) where T : class`
|
||||
* Registers a service implementation `item` under the interface type `T`.
|
||||
* Throws `ArgumentException` if `T` is already registered.
|
||||
* `public static void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)`
|
||||
* Registers a single object `item` as the implementation for multiple interfaces defined in `interfaceList`.
|
||||
* If `skipPublishedInterfaces` is `false`, throws `ArgumentException` if any interface in the list is already registered.
|
||||
* If `skipPublishedInterfaces` is `true`, silently skips already registered interfaces.
|
||||
* `public static bool Exists() where T : class`
|
||||
* Returns `true` if a service of interface type `T` is currently registered; otherwise `false`.
|
||||
* `public static bool Exists(Type t)`
|
||||
* Non-generic overload. Returns `true` if the specified `Type t` is registered; otherwise `false`.
|
||||
* `public static T Get() where T : class`
|
||||
* Retrieves the registered service implementation for interface type `T`.
|
||||
* Throws `ArgumentException` if `T` has not been published.
|
||||
* `public static void Clear() where T : class`
|
||||
* Un-registers the service for interface type `T`. Fires an "unpublished" event.
|
||||
* `public static void Clear(IEnumerable<Type> interfaceList)`
|
||||
* Un-registers all services for the types specified in `interfaceList`. Fires "unpublished" events for each removed service.
|
||||
|
||||
## 3. Invariants
|
||||
* **Uniqueness:** The `ServiceManager` enforces a one-to-one mapping between a `Type` and a service instance. A `Type` cannot be published twice unless the previous instance is cleared or the batch publish method is used with `skipPublishedInterfaces` set to `true`.
|
||||
* **Reference Types Only:** All generic methods (`Publish`, `Exists`, `Get`, `Clear`) constrain the type parameter `T` to `class`.
|
||||
* **Event Ordering:** When clearing a service, the `IServicePublishedEvent` (with `IsPublished = false`) is fired **before** the service is removed from the internal dictionary.
|
||||
* **Exception Consistency:** Both `Publish<T>` and `Get<T>` throw `ArgumentException` (not a custom exception type) for invalid states (already exists / not found).
|
||||
|
||||
## 4. Dependencies
|
||||
* **Dependencies (Internal):**
|
||||
* `ServiceManager` depends on `ServicePublishedEvent` to create event payloads.
|
||||
* `ServicePublishedEvent` depends on `IServicePublishedEvent`.
|
||||
* **Dependencies (External):**
|
||||
* `ServiceManager` depends on `EventManager.EventManager`. The private method `SendServicePublishedEvent` calls `EventManager.EventManager.Publish<IServicePublishedEvent>(...)`. The location/assembly of `EventManager` is not defined in the provided source but is required for this module to compile and run.
|
||||
* **Standard Libraries:** `System`, `System.Collections.Generic`.
|
||||
|
||||
## 5. Gotchas
|
||||
* **Thread Safety:** The internal storage `Dictionary<Type, object> Services` uses standard `System.Collections.Generic.Dictionary`. There are no locks or synchronization mechanisms in `ServiceManager`. This module is **not thread-safe**. Concurrent calls to `Publish`, `Get`, or `Clear` may result in race conditions or corruption.
|
||||
* **Event Manager Coupling:** The `ServiceManager` is tightly coupled to a specific `EventManager.EventManager` class. If that event manager is not initialized or accessible, the `Publish` and `Clear` methods will fail at runtime when attempting to broadcast events.
|
||||
* **Silent Failures in Batch Publish:** When calling `Publish(object, IEnumerable<Type>, bool)` with `skipPublishedInterfaces` set to `true`, the method will silently ignore interfaces that are already registered. This could lead to stale service instances remaining active if the caller assumed the new `item` would replace them.
|
||||
* **Clear Event Timing:** Because the "unpublished" event fires before the item is removed from the dictionary, an event subscriber handling `IServicePublishedEvent` with `IsPublished == false` could technically still call `ServiceManager.Exists(type)` and receive `true` inside their event handler.
|
||||
Reference in New Issue
Block a user