init
This commit is contained in:
104
enriched-partialglm/Common/DTS.Common.Core/Config.md
Normal file
104
enriched-partialglm/Common/DTS.Common.Core/Config.md
Normal file
@@ -0,0 +1,104 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Core/Config/DTSConfig.cs
|
||||
generated_at: "2026-04-16T11:41:16.907673+00:00"
|
||||
model: "zai-org/GLM-5-FP8"
|
||||
schema_version: 1
|
||||
sha256: "2693b2d1a0d0acee"
|
||||
---
|
||||
|
||||
# Documentation: DTSConfig.cs
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
`DTSConfig` is a static utility class that provides centralized access to application configuration settings from an alternate configuration file. It exists to allow the application to read settings from a custom `.config` file path rather than the default application configuration, supporting scenarios where configuration needs to be externalized or shared across components. The class acts as a configuration facade, wrapping `System.Configuration.ConfigurationManager` functionality with thread-safe access and logging for missing keys or sections.
|
||||
|
||||
---
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `AltConfigPathGet()`
|
||||
**Signature:** `public static string AltConfigPathGet()`
|
||||
|
||||
Returns the currently set alternate configuration file path. Thread-safe via locking on `MyLock`.
|
||||
|
||||
---
|
||||
|
||||
### `AltConfigPathSet(string path)`
|
||||
**Signature:** `public static void AltConfigPathSet(string path)`
|
||||
|
||||
Sets the alternate configuration file path. Updates `AltConfigPath` only; does not reload the configuration. Thread-safe via locking on `MyLock`.
|
||||
|
||||
---
|
||||
|
||||
### `DTSConfigInit(string path)`
|
||||
**Signature:** `public static void DTSConfigInit(string path)`
|
||||
|
||||
Initializes the configuration system by calling `SetAltConfigPath(path)`. This is the primary entry point for setting up the alternate configuration at application startup.
|
||||
|
||||
---
|
||||
|
||||
### `GetAltConfig()`
|
||||
**Signature:** `public static Configuration GetAltConfig()`
|
||||
|
||||
Returns the `System.Configuration.Configuration` object representing the loaded alternate configuration file. Thread-safe via locking on `MyLock`.
|
||||
|
||||
---
|
||||
|
||||
### `SetAltConfigPath(string path)`
|
||||
**Signature:** `public static void SetAltConfigPath(string path)`
|
||||
|
||||
Sets the alternate configuration path and immediately loads the configuration file. If `path` is null or empty, falls back to `DTSConstants.CustomConfigPath`. Creates an `ExeConfigurationFileMap` and opens the configuration via `ConfigurationManager.OpenMappedExeConfiguration`. Thread-safe via locking on `MyLock`.
|
||||
|
||||
---
|
||||
|
||||
### `GetAppSetting(string key)`
|
||||
**Signature:** `public static string GetAppSetting(string key)`
|
||||
|
||||
Retrieves an application setting value by key from the alternate configuration's `AppSettings` section. Returns `string.Empty` if the key is not found (logs a warning via `APILogger.Log`). Does not throw exceptions for missing keys.
|
||||
|
||||
---
|
||||
|
||||
### `GetSection(string sectionName)`
|
||||
**Signature:** `public static object GetSection(string sectionName)`
|
||||
|
||||
Retrieves a configuration section by name from the alternate configuration. Returns `null` if the section is not found (logs a warning via `APILogger.Log`). Used by plugin code to retrieve plugin library sections.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Thread Safety:** All access to static fields (`AltConfigPath`, `AltConfig`) is protected by a lock on `MyLock`.
|
||||
- **Configuration Initialization:** `AltConfig` is populated when `SetAltConfigPath()` is called; calling `GetAppSetting()` or `GetSection()` before initialization will result in a `NullReferenceException` (not guarded against in source).
|
||||
- **Fallback Path:** When `SetAltConfigPath(string path)` receives a null or empty path, it uses `DTSConstants.CustomConfigPath` as the configuration file location.
|
||||
- **Missing Key Handling:** `GetAppSetting()` returns `string.Empty` for missing keys rather than `null` or throwing an exception.
|
||||
- **Missing Section Handling:** `GetSection()` returns `null` for missing sections and logs the absence.
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### This module depends on:
|
||||
- `DTS.Common.Utilities.Logging` — Uses `APILogger.Log()` for warning messages
|
||||
- `System.Configuration` — Uses `Configuration`, `ConfigurationManager`, `ExeConfigurationFileMap`, `KeyValueConfigurationElement`, `ConfigurationUserLevel`
|
||||
- `System.Linq` — Uses `Cast<>()` and `FirstOrDefault()`
|
||||
- `DTSConstants.CustomConfigPath` — Referenced constant (defined elsewhere, location not shown in source)
|
||||
|
||||
### What depends on this module:
|
||||
- **Unclear from source alone** — No consumers are shown in this file. The `GetSection()` method documentation mentions "plugin code" as a consumer.
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
1. **Redundant API Surface:** Both `DTSConfigInit()` and `SetAltConfigPath()` perform the same operation. `DTSConfigInit()` simply delegates to `SetAltConfigPath()` with no additional logic.
|
||||
|
||||
2. **Inconsistent Naming Convention:** The class exposes both `AltConfigPathGet()/AltConfigPathSet()` (Java-style) and `SetAltConfigPath()` (C#-style) methods for similar operations, creating potential confusion.
|
||||
|
||||
3. **Uninitialized State Not Guarded:** Calling `GetAppSetting()` or `GetSection()` before `SetAltConfigPath()` or `DTSConfigInit()` will throw a `NullReferenceException` since `AltConfig` starts as `null`.
|
||||
|
||||
4. **Empty Static Constructor:** The static constructor is explicitly defined but empty, which is unnecessary.
|
||||
|
||||
5. **Silent Failure on Missing Keys:** Missing configuration keys return `string.Empty` rather than throwing, which may mask configuration errors. Consumers must check for empty string rather than null.
|
||||
|
||||
6. **ReSharper Suppressions:** The file suppresses `InconsistentNaming` warnings, suggesting naming conventions in this file deviate from project standards.
|
||||
73
enriched-partialglm/Common/DTS.Common.Core/EventManager.md
Normal file
73
enriched-partialglm/Common/DTS.Common.Core/EventManager.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Core/EventManager/EventManager.cs
|
||||
generated_at: "2026-04-16T11:42:05.172295+00:00"
|
||||
model: "zai-org/GLM-5-FP8"
|
||||
schema_version: 1
|
||||
sha256: "59cbfaadaa1e572f"
|
||||
---
|
||||
|
||||
# Documentation: DTS.Common.Core.EventManager
|
||||
|
||||
## 1. Purpose
|
||||
The `EventManager` class provides a static, global implementation of the Publish/Subscribe (Pub/Sub) pattern. It enables decoupled communication between system components, allowing publishers to emit events without knowledge of subscribers, and subscribers to react to events without direct coupling to publishers. Additionally, it provides a diagnostic infrastructure to monitor the event system's activity, such as tracking subscription counts and event publication flow.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Delegates
|
||||
* **`SubscriberCallbackDelegate<in T>(T item)`**
|
||||
* The signature required for methods subscribing to events.
|
||||
* Constraint: `T` must be a reference type (`class`).
|
||||
* **`DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener)`**
|
||||
* The signature required for methods subscribing to diagnostic events regarding the EventManager's internal operations.
|
||||
|
||||
### Static Class: `EventManager`
|
||||
|
||||
#### Methods
|
||||
* **`void Publish(T eventData) where T : class`**
|
||||
* Publishes an event of type `T` to all registered subscribers.
|
||||
* Iterates through the subscriber list for type `T`. If a subscriber has an `EventFilter`, the filter is evaluated; the callback is invoked only if the filter returns `true`.
|
||||
* If no subscribers exist for type `T`, the method returns immediately without throwing an exception.
|
||||
* **`void Subscribe(SubscriberCallbackDelegate listener) where T : class`**
|
||||
* Registers a listener for event type `T` without a filter.
|
||||
* Overload: `void Subscribe(SubscriberCallbackDelegate listener, Predicate eventFilter) where T : class`
|
||||
* Registers a listener with a predicate filter. The callback will only be invoked if `eventFilter(eventData)` returns `true`.
|
||||
* **`void UnSubscribe(SubscriberCallbackDelegate listener) where T : class`**
|
||||
* Removes a specific listener from the subscriber list for type `T`.
|
||||
* Uses the `Callback` delegate equality to find and remove the matching `EventMetaData`.
|
||||
* **`void Clear()`**
|
||||
* Removes all listeners for all event types from the `SubscriberList`.
|
||||
* **`void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)`**
|
||||
* Registers a listener to receive diagnostic events (e.g., when items are added or removed).
|
||||
* **`void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)`**
|
||||
* Removes a specific listener from the diagnostic events list.
|
||||
* **`void ClearDiagnosticEvents()`**
|
||||
* Removes all listeners from the diagnostic events list.
|
||||
|
||||
### Enum: `EventDiagnosticType`
|
||||
Defines the types of diagnostic events generated by the system.
|
||||
* `AddListener` (0)
|
||||
* `AddListenerDiagnostic` (1)
|
||||
* `PublishEvent` (2)
|
||||
* `RemoveListenerDiagnostic` (3)
|
||||
* `RemoveListener` (4)
|
||||
|
||||
## 3. Invariants
|
||||
* **Type Constraint:** All event types `T` used in `Publish`, `Subscribe`, and `UnSubscribe` must be reference types (`class`).
|
||||
* **Thread Safety:** The source code does not contain any locking mechanisms (e.g., `lock`, `Monitor`) around the static `Dictionary` or `List` collections. The module assumes a single-threaded execution context or requires external synchronization by the caller.
|
||||
* **Reference Equality:** Unsubscription relies on delegate reference equality. A subscriber must pass the exact same delegate instance used during `Subscribe` to successfully `UnSubscribe`.
|
||||
* **Internal Storage:** Listeners are stored internally as `EventMetaData` objects within a `List<object>`, despite the dictionary value type being `List<object>`.
|
||||
|
||||
## 4. Dependencies
|
||||
* **Internal Dependencies:**
|
||||
* `System.Collections.Generic` (for `Dictionary`, `List`, `Predicate`)
|
||||
* `System.Reflection` (for `MemberInfo`, `Type` used in diagnostics)
|
||||
* **External Dependencies:**
|
||||
* None identified from the source file alone. As a core utility, it is likely widely depended upon by higher-level application modules.
|
||||
|
||||
## 5. Gotchas
|
||||
* **Thread Safety Risk:** The `SubscriberList` and `DiagnosticList` are static and mutable. Concurrent calls to `Subscribe`/`Publish` from different threads will cause race conditions and likely throw exceptions (e.g., `InvalidOperationException` on the list enumerator during `Publish`).
|
||||
* **Diagnostic "Clear" Behavior:** The `ClearDiagnosticEvents()` method clears the `DiagnosticList` *before* sending the final `RemoveListenerDiagnostic` event. Consequently, the final diagnostic event is sent to an empty list and will effectively be lost/ignored.
|
||||
* **Diagnostic Noise during Publish:** The `Publish` method sends a `PublishEvent` diagnostic message *inside* the loop for every single subscriber. If one event has 10 subscribers, 10 diagnostic events are fired for a single `Publish` call.
|
||||
* **Memory Leaks:** Because `SubscriberList` is static and holds references to delegate targets, failing to call `UnSubscribe` will prevent the subscriber objects from being garbage collected.
|
||||
* **Silent Failures:** `Publish` silently ignores the event if no subscribers are registered. `UnSubscribe` silently does nothing if the listener is not found.
|
||||
149
enriched-partialglm/Common/DTS.Common.Core/PluginLib.md
Normal file
149
enriched-partialglm/Common/DTS.Common.Core/PluginLib.md
Normal file
@@ -0,0 +1,149 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Core/PluginLib/PluginConfigData.cs
|
||||
- Common/DTS.Common.Core/PluginLib/PluginConfig.cs
|
||||
- Common/DTS.Common.Core/PluginLib/PluginConfigSectionHandler.cs
|
||||
- Common/DTS.Common.Core/PluginLib/PluginManager.cs
|
||||
generated_at: "2026-04-16T11:42:06.536831+00:00"
|
||||
model: "zai-org/GLM-5-FP8"
|
||||
schema_version: 1
|
||||
sha256: "698a84042cfeb418"
|
||||
---
|
||||
|
||||
# PluginLib Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
The `PluginLib` module provides a Managed Extensibility Framework (MEF)-based plugin infrastructure for the DTS system. It handles discovery, loading, and retrieval of plugins from configurable directories, supporting both single-plugin resolution and multiple implementations of the same interface. The module abstracts configuration management through custom configuration section handlers and provides thread-safe singleton access to the plugin catalog and container.
|
||||
|
||||
---
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `PluginManager` (Class)
|
||||
The primary entry point for plugin operations.
|
||||
|
||||
| Method | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `GetPluginManager` | `public static PluginManager GetPluginManager(string appPath)` | Returns the singleton instance of `PluginManager`. Initializes the plugin system on first call with the provided `appPath`. Thread-safe via lock on `THREAD_LOCK`. |
|
||||
| `GetPlugin<T>` | `public static T GetPlugin<T>() where T : class` | Retrieves a single MEF export of type `T`. Returns `null` if no export exists. Throws if multiple exports exist for the same type. |
|
||||
| `GetPlugin<T>` | `public static T GetPlugin<T>(string configPluginSetting) where T : class` | Retrieves a specific plugin from multiple exports by matching `configPluginSetting` against the plugin's `ToString()` value. |
|
||||
| `GetPlugins<T>` | `public static IEnumerable<Lazy<T>> GetPlugins<T>() where T : class` | Returns all MEF exports of type `T` as lazy-initialized references. |
|
||||
| `GetPluginList<T>` | `public List<Assembly> GetPluginList<T>() where T : class` | Returns a list of distinct `Assembly` objects from all loaded directory catalogs. Note: The generic type parameter `T` is not used in the implementation. |
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `PluginCatalog` | `AggregateCatalog` | The MEF aggregate catalog containing all loaded plugin directories. |
|
||||
|
||||
---
|
||||
|
||||
### `PluginConfig` (Static Class)
|
||||
Provides configuration helper methods.
|
||||
|
||||
| Member | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `DTSPlugins` | `public const string DTSPlugins = "DTSPlugins"` | Constant for the app setting key name. |
|
||||
| `GetDTSPluginsSetting` | `public static string GetDTSPluginsSetting(string setting)` | Concatenates the app setting value for `DTSPlugins` with the provided `setting` parameter using `.` as separator. |
|
||||
|
||||
---
|
||||
|
||||
### `PluginConfigSectionHandler` (Class)
|
||||
Configuration section handler for `DTS.Common.Core.PluginLib.Config`.
|
||||
|
||||
| Property | Type | Description |
|
||||
|----------|------|-------------|
|
||||
| `HashKeys` | `FilterHashKeyCollection` | Returns the collection of plugin folder elements from the configuration section. |
|
||||
|
||||
---
|
||||
|
||||
### `FilterHashKeyCollection` (Class)
|
||||
Collection class for configuration elements.
|
||||
|
||||
| Member | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| `this[int idx]` | `public FilterHashElement this[int idx]` | Indexer to access elements by position. |
|
||||
|
||||
---
|
||||
|
||||
### `FilterHashElement` (Class)
|
||||
Represents a single plugin folder configuration entry.
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
|----------|------|----------|-------------|
|
||||
| `Key` | `string` | Yes | The key identifier for the element. |
|
||||
| `Value` | `string` | No | The plugin directory path. |
|
||||
|
||||
---
|
||||
|
||||
### `PluginConfigData` (Class)
|
||||
XML serialization support class for legacy configuration format.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `PluginFolders` | `string[]` | Array of plugin folder paths. Serialized with `XmlArrayItem("Folder")` attribute. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
1. **Singleton Pattern**: `_pluginManager` is a static singleton; once initialized, subsequent calls to `GetPluginManager` return the existing instance regardless of the `appPath` parameter passed.
|
||||
|
||||
2. **Thread Safety**: All access to the singleton initialization is protected by `THREAD_LOCK` object.
|
||||
|
||||
3. **Configuration Requirement**: The configuration section `"DTS.Common.Core.PluginLib.Config"` must exist in the application configuration file, or the `PluginManager` constructor throws an `Exception`.
|
||||
|
||||
4. **Directory Existence**: All plugin directories specified in `FilterHashElement.Value` must exist at initialization time, or an `IOException` is thrown.
|
||||
|
||||
5. **Assembly Exclusion**: Assemblies with names starting with `"DTS.Common"`, `"C1"`, or `"Xceed"` are explicitly excluded from manual assembly loading in the constructor.
|
||||
|
||||
6. **MEF Export Uniqueness**: `GetPlugin<T>()` (the parameterless overload) expects exactly zero or one export of type `T`; MEF throws an exception if multiple exports exist.
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### This module depends on:
|
||||
- `DTS.Common.Core.Config` - For `DTSConfig.GetSection()`, `DTSConfig.GetAppSetting()`, and `DTSConfig.DTSConfigInit()`
|
||||
- `DTS.Common.Utilities.Logging` - For `APILogger.Log()` static method
|
||||
- `System.ComponentModel.Composition.Hosting` - MEF container and catalog types
|
||||
- `System.ComponentModel.Composition.ReflectionModel` - For `ReflectionModelServices.GetPartType()`
|
||||
- `System.Configuration` - For configuration section infrastructure
|
||||
- `System.Xml.Serialization` - For `PluginConfigData` XML serialization
|
||||
|
||||
### Consumers:
|
||||
- Any module requiring plugin extensibility via MEF exports
|
||||
- Code calling `PluginManager.GetPlugin<T>()` or `PluginManager.GetPlugins<T>()`
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
1. **Unused Assembly Resolve Handler**: The method `CurrentDomain_AssemblyResolve` is defined but **never wired up** to `AppDomain.CurrentDomain.AssemblyResolve`. It will never be called unless external code attaches it.
|
||||
|
||||
2. **Configuration Section Name Inconsistency**: `PluginConfigData` is decorated with `[XmlRoot(ElementName = "DatPro.Core.PluginLib.Config")]` (legacy "DatPro" naming), while `PluginManager` looks for `"DTS.Common.Core.PluginLib.Config"`. These are different section names; `PluginConfigData` appears to be legacy/unused code.
|
||||
|
||||
3. **Unused Parameter in GetPluginList**: The generic type parameter `T` in `GetPluginList<T>()` is declared but never used in the method body. The method returns all assemblies regardless of type.
|
||||
|
||||
4. **Dead Code Before Lock**: In `GetPluginManager()`, a `DirectoryInfo` object is created from `appPath` before the lock but never used:
|
||||
```csharp
|
||||
if (!string.IsNullOrWhiteSpace(appPath))
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(appPath);
|
||||
}
|
||||
```
|
||||
|
||||
5. **Empty Loop Bodies**: The singleton check contains loops with empty bodies:
|
||||
```csharp
|
||||
foreach (var catalog in _pluginManager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
}
|
||||
```
|
||||
This appears to be vestigial code with no effect.
|
||||
|
||||
6. **Plugin Matching via ToString()**: `GetPlugin<T>(string configPluginSetting)` matches plugins by comparing `item.Value.ToString()` to `configPluginSetting`. This relies on the plugin's `ToString()` override returning a meaningful identifier.
|
||||
|
||||
7. **Null Return Possible**: `GetPlugin<T>()` returns `null` if no export is found, not an exception. Callers must handle null.
|
||||
|
||||
8. **Hardcoded Assembly Exclusions**: The exclusion list (`"DTS.Common"`, `"C1"`, `"Xceed"`) is hardcoded in the constructor and not configurable.
|
||||
43
enriched-partialglm/Common/DTS.Common.Core/Properties.md
Normal file
43
enriched-partialglm/Common/DTS.Common.Core/Properties.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Core/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T11:42:40.333369+00:00"
|
||||
model: "zai-org/GLM-5-FP8"
|
||||
schema_version: 1
|
||||
sha256: "f157b2a2cacdeb5d"
|
||||
---
|
||||
|
||||
# Documentation: DTS.Common.Core Assembly Metadata
|
||||
|
||||
## 1. Purpose
|
||||
This file provides assembly-level metadata and configuration for the `DTS.Common.Core` library. It defines the assembly's identity, version information, and COM visibility settings using .NET attributes. This module exists to embed standard manifest information into the compiled DLL, facilitating identification, versioning, and interop configuration within the larger DTS system.
|
||||
|
||||
## 2. Public Interface
|
||||
This file does not contain public classes or methods. It defines the following assembly-level attributes:
|
||||
|
||||
* **`AssemblyTitle`**: Set to `"DTS.Common.Core"`.
|
||||
* **`AssemblyDescription`**: Set to an empty string.
|
||||
* **`AssemblyConfiguration`**: Set to an empty string.
|
||||
* **`AssemblyCompany`**: Set to an empty string.
|
||||
* **`AssemblyProduct`**: Set to `"DTS.Common.Core"`.
|
||||
* **`AssemblyCopyright`**: Set to `"Copyright © 2016"`.
|
||||
* **`AssemblyTrademark`**: Set to an empty string.
|
||||
* **`AssemblyCulture`**: Set to an empty string (indicates the assembly is culture-neutral).
|
||||
* **`ComVisible`**: Set to `false`. This makes types in the assembly invisible to COM components.
|
||||
* **`Guid`**: Set to `"bdf5ad7a-51db-4ad0-8186-d1ead7405848"`. This is the unique identifier for the typelib if exposed to COM.
|
||||
* **`AssemblyVersion`**: Set to `"1.0.0.0"`.
|
||||
* **`AssemblyFileVersion`**: Set to `"1.0.0.0"`.
|
||||
|
||||
## 3. Invariants
|
||||
* **COM Visibility:** Types within this assembly are explicitly non-visible to COM components unless individually overridden.
|
||||
* **Culture Neutrality:** The assembly is marked with an empty `AssemblyCulture`, indicating it is not a satellite assembly and is culture-neutral.
|
||||
* **Version Synchronization:** The `AssemblyVersion` and `AssemblyFileVersion` are currently synchronized at `1.0.0.0`.
|
||||
|
||||
## 4. Dependencies
|
||||
* **Internal Dependencies:** This file imports `System.Reflection`, `System.Runtime.CompilerServices`, and `System.Runtime.InteropServices`.
|
||||
* **External Consumers:** Cannot be determined from this source file alone. Any project referencing the compiled `DTS.Common.Core.dll` depends on this metadata.
|
||||
|
||||
## 5. Gotchas
|
||||
* **Hardcoded Versions:** The version numbers (`1.0.0.0`) are hardcoded strings. If the project uses CI/CD pipelines to auto-increment versions, this file may need to be updated or the build process configured to overwrite these attributes.
|
||||
* **Missing Metadata:** `AssemblyDescription`, `AssemblyCompany`, and `AssemblyConfiguration` are empty. This may lack context for developers inspecting the DLL properties.
|
||||
* **Legacy Format:** This file structure suggests an older .NET Framework project style (non-SDK style). Modern .NET Core/5+ projects often embed this information in the `.csproj` file, potentially leading to duplication or confusion if the project is ever migrated.
|
||||
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.
|
||||
114
enriched-partialglm/Common/DTS.Common.Core/Settings.md
Normal file
114
enriched-partialglm/Common/DTS.Common.Core/Settings.md
Normal file
@@ -0,0 +1,114 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Core/Settings/SettingsChangedEventArgs.cs
|
||||
- Common/DTS.Common.Core/Settings/SettingsCollection.cs
|
||||
generated_at: "2026-04-16T11:41:07.381293+00:00"
|
||||
model: "zai-org/GLM-5-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e48bcdd1082dba01"
|
||||
---
|
||||
|
||||
# Documentation: DTS.Common.Core.Settings
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides an observable dictionary implementation that notifies subscribers when settings change. It consists of `SettingsCollection<TKey, TItem>`, a generic dictionary wrapper that implements `IDictionary<TKey, TItem>` and fires events on modifications, and `SettingsChangedEventArgs<TKey, TItem>`, the event payload describing what changed. This enables reactive patterns where consumers can respond to configuration or settings changes without polling.
|
||||
|
||||
---
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `SettingsCollection<TKey, TItem>`
|
||||
|
||||
A generic dictionary implementation that raises events on mutation.
|
||||
|
||||
**Event:**
|
||||
- `event EventHandler<SettingsChangedEventArgs<TKey, TItem>> CollectionItemPropertyChanged` — Fired after any add, remove, modify, or clear operation.
|
||||
|
||||
**Constructors:**
|
||||
- None explicitly defined; uses default constructor.
|
||||
|
||||
**Properties:**
|
||||
- `ICollection<TKey> Keys { get; }` — Returns all keys in the collection. Delegates to internal dictionary.
|
||||
- `ICollection<TItem> Values { get; }` — Returns all values in the collection. Delegates to internal dictionary.
|
||||
- `TItem this[TKey key] { get; set; }` — Indexer. Getter returns value for key; setter assigns value and fires `ChangeSettingType.Add` event.
|
||||
- `int Count { get; }` — Returns count of items.
|
||||
- `bool IsReadOnly { get; }` — Always returns `false`.
|
||||
|
||||
**Methods:**
|
||||
- `void Add(TKey key, TItem value)` — Adds key-value pair; fires `ChangeSettingType.Add` event.
|
||||
- `void Add(KeyValuePair<TKey, TItem> item)` — Adds key-value pair; fires `ChangeSettingType.Add` event.
|
||||
- `bool ContainsKey(TKey key)` — Returns `true` if key exists.
|
||||
- `bool Contains(KeyValuePair<TKey, TItem> item)` — Returns `true` if both key and value match an entry.
|
||||
- `bool Remove(TKey key)` — Removes by key; fires `ChangeSettingType.Remove` event if successful. Returns success boolean.
|
||||
- `bool Remove(KeyValuePair<TKey, TItem> item)` — Removes by key (ignores value); fires `ChangeSettingType.Remove` event if successful. Returns success boolean.
|
||||
- `bool TryGetValue(TKey key, out TItem value)` — Attempts to retrieve value for key.
|
||||
- `void Clear()` — Clears all items; fires `ChangeSettingType.ClearAll` event.
|
||||
- `void CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)` — **Throws `NotImplementedException`.**
|
||||
- `IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()` — Returns enumerator.
|
||||
- `IEnumerator IEnumerable.GetEnumerator()` — Returns non-generic enumerator.
|
||||
|
||||
---
|
||||
|
||||
### `SettingsChangedEventArgs<TKey, TItem>`
|
||||
|
||||
Event arguments describing a settings change.
|
||||
|
||||
**Constructors:**
|
||||
- `SettingsChangedEventArgs(ChangeSettingType changeType)` — Initializes with change type only.
|
||||
- `SettingsChangedEventArgs(ChangeSettingType changeType, TKey key)` — Initializes with change type and key.
|
||||
- `SettingsChangedEventArgs(ChangeSettingType changeType, TKey key, TItem item)` — Initializes with change type, key, and item.
|
||||
|
||||
**Properties:**
|
||||
- `ChangeSettingType ChangeType { get; }` — The type of change (read-only).
|
||||
- `TKey Key { get; }` — The key associated with the change (read-only).
|
||||
- `TItem Item { get; }` — The value associated with the change (read-only).
|
||||
|
||||
---
|
||||
|
||||
### `ChangeSettingType` (enum)
|
||||
|
||||
Defines the type of settings change.
|
||||
|
||||
| Value | Name | Numeric Value |
|
||||
|-------|------|---------------|
|
||||
| `Add` | Item added | 0 |
|
||||
| `Remove` | Item removed | 1 |
|
||||
| `Modified` | Item modified | 3 |
|
||||
| `ClearAll` | Collection cleared | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Event firing occurs after mutation:** Events are fired only after the underlying dictionary has been successfully modified (e.g., `Remove` fires only if removal succeeded).
|
||||
- **Key and Item properties may be default/uninitialized:** Depending on which constructor is used, `Key` and `Item` may be `default(TKey)` or `default(TItem)` respectively. Consumers should check `ChangeType` to determine which properties are meaningful.
|
||||
- `IsReadOnly` always returns `false`.
|
||||
- The internal `_items` dictionary is never null (initialized at declaration).
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
**This module depends on:**
|
||||
- `System` (for `EventArgs`, `EventHandler<T>`)
|
||||
- `System.Collections` (for `IEnumerable`)
|
||||
- `System.Collections.Generic` (for `IDictionary<TKey, TItem>`, `Dictionary<TKey, TItem>`, `ICollection<T>`, `KeyValuePair<TKey, TItem>`)
|
||||
|
||||
**Consumers (inferred):**
|
||||
- Any module requiring observable settings/configuration storage.
|
||||
- Cannot determine specific consumers from source alone.
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
1. **Indexer setter uses `ChangeSettingType.Add`, not `Modified`:** The indexer `this[TKey key]` setter always fires `ChangeSettingType.Add`, even when overwriting an existing key. The `Modified` enum value (3) is never used in this implementation.
|
||||
|
||||
2. **`CopyTo` is not implemented:** Calling `CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)` throws `NotImplementedException`. This will cause runtime failures if the collection is used with APIs that call `CopyTo`.
|
||||
|
||||
3. **`Remove(KeyValuePair<TKey, TItem>)` ignores the value:** The `Remove(KeyValuePair<TKey, TItem> item)` method only checks and removes by key, ignoring `item.Value`. This differs from typical `IDictionary` implementations that verify the value matches before removal.
|
||||
|
||||
4. **Enum has a gap:** `ChangeSettingType` has values 0, 1, 3, 4 — value 2 is skipped. This may indicate a removed/renamed value or historical artifact.
|
||||
|
||||
5. **No validation on constructor arguments:** `SettingsChangedEventArgs` constructors do not validate that `Key` and `Item` are provided when `ChangeType` would logically require them (e.g., `Add` without a key/item).
|
||||
Reference in New Issue
Block a user