init
This commit is contained in:
75
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/Config.md
Normal file
75
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/Config.md
Normal file
@@ -0,0 +1,75 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/DataPRO.Core/Config/DataProConfig.cs
|
||||
generated_at: "2026-04-16T04:27:34.469920+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "c18420fbff70f9a1"
|
||||
---
|
||||
|
||||
# Config
|
||||
|
||||
## Documentation: `DataProConfig` Module
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module provides centralized, static access to application configuration settings loaded from a *custom* configuration file (as specified by `DataProConstants.CustomConfigPath`). It abstracts the underlying `ConfigurationManager` mechanics to enable consistent retrieval of `<appSettings>` values and arbitrary configuration sections across the codebase—particularly by plugin code that requires access to non-standard configuration sections. Its existence ensures decoupling from direct `ConfigurationManager` usage and enforces use of a dedicated configuration file rather than the default `app.config`/`web.config`.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `public static Configuration AltConfig { get; }`
|
||||
- **Type**: Static property
|
||||
- **Behavior**: Returns the `Configuration` object loaded from the custom config file path (`DataProConstants.CustomConfigPath`). This is the primary handle to the entire configuration structure.
|
||||
- **Note**: The property name `AltConfig` is misleading—it is *not* an alternate; it is the *primary* configuration source for this module.
|
||||
|
||||
#### `public static string GetAppSetting(string key)`
|
||||
- **Type**: Static method
|
||||
- **Signature**: `string GetAppSetting(string key)`
|
||||
- **Behavior**: Retrieves the value of an `<add key="..." value="..." />` entry from the `<appSettings>` section of the custom config file. Returns `string.Empty` if the key is not found.
|
||||
- **Implementation detail**: Uses LINQ over `Config.AppSettings.Settings` (cast to `KeyValueConfigurationElement`) to locate the matching key.
|
||||
|
||||
#### `public static object GetSection(string sectionName)`
|
||||
- **Type**: Static method
|
||||
- **Signature**: `object GetSection(string sectionName)`
|
||||
- **Behavior**: Retrieves a custom configuration section (e.g., `<pluginLibrary>`, `<dataSources>`) by name from the custom config file. Returns `null` if the section is not defined or fails to load.
|
||||
- **Intended use**: Designed for plugin code to deserialize and consume plugin-specific configuration sections.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- The configuration file path is *fixed at initialization* and derived from `DataProConstants.CustomConfigPath`.
|
||||
- The configuration is loaded **once** during static initialization (via static constructor) and never reloaded during the application lifetime.
|
||||
- `GetAppSetting` **never throws** on missing keys—it returns `string.Empty`.
|
||||
- `GetSection` may return `null` if the section does not exist or fails to deserialize (e.g., due to schema mismatch), but the source does not indicate explicit error handling or logging.
|
||||
- The `Configuration` object (`Config`) is opened with `openReadOnly: true` (third parameter `true` in `OpenMappedExeConfiguration`), meaning writes are disallowed.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### Dependencies *on*:
|
||||
- `System.Configuration.ConfigurationManager` (for `OpenMappedExeConfiguration`, `GetSection`, `AppSettings`)
|
||||
- `System.Configuration` types: `Configuration`, `ExeConfigurationFileMap`, `ConfigurationUserLevel`, `KeyValueConfigurationElement`
|
||||
- `DataProConstants.CustomConfigPath` (assumed to be a `string` constant defining the path to the custom config file)
|
||||
|
||||
#### Dependencies *of*:
|
||||
- Plugin modules (via `GetSection`) to load plugin-specific configuration.
|
||||
- Any code needing access to `<appSettings>` or custom sections defined in the custom config file.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **Static initialization timing**: The config file is loaded at first access to *any* member of `DataProConfig`. If `DataProConstants.CustomConfigPath` points to a non-existent or inaccessible file, the static constructor will throw (e.g., `ConfigurationErrorsException`), potentially crashing app startup.
|
||||
- **No fallback behavior**: `GetAppSetting` returns `string.Empty` for missing keys—callers must explicitly check for this (e.g., `string.IsNullOrEmpty`) rather than relying on `null`.
|
||||
- **No validation**: Neither `GetAppSetting` nor `GetSection` validates the content or type of returned values. Consumers must handle parsing, casting, and validation themselves.
|
||||
- **Misleading property name**: `AltConfig` implies it is *optional* or *secondary*, but it is the *only* configuration source used by this module.
|
||||
- **No thread-safety documentation**: While `Configuration` objects are generally safe for concurrent reads, the source does not explicitly guarantee thread-safety.
|
||||
- **Assumes `<appSettings>` structure**: `GetAppSetting` assumes the config file contains a standard `<appSettings>` section; it does not handle custom section-based key-value storage.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/DataPRO.Core/EventManager/EventManager.cs
|
||||
generated_at: "2026-04-16T04:27:50.546850+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "563530faa0be756e"
|
||||
---
|
||||
|
||||
# EventManager
|
||||
|
||||
## Documentation: `EventManager` Module
|
||||
|
||||
### 1. Purpose
|
||||
The `EventManager` class provides a central, static event-publishing/subscribing mechanism that decouples event producers from consumers. It enables components to publish typed events (`Publish<T>`) and subscribe to them with optional filtering (`Subscribe<T>`), while maintaining a diagnostic logging capability for runtime introspection. This module exists to support loose coupling in the system, avoiding direct dependencies between event emitters and listeners, and to aid debugging and monitoring via diagnostic events.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
- **`delegate void SubscriberCallbackDelegate<in T>(T item) where T : class`**
|
||||
Signature for event listener callbacks. Receives the event payload (`item`) of type `T`.
|
||||
|
||||
- **`delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener)`**
|
||||
Signature for diagnostic event callbacks. Reports internal `EventManager` operations (e.g., add/remove listener, publish event) with context:
|
||||
- `eventType`: Kind of operation (`EventDiagnosticType`)
|
||||
- `t`: Event type being subscribed/published
|
||||
- `eventData`: Event payload (may be `null` for subscription/unsubscription events)
|
||||
- `listener`: Fully qualified method name and assembly (e.g., `"MyNamespace.MyClass.MyMethod, MyAssembly"`)
|
||||
|
||||
- **`static void Publish<T>(T eventData) where T : class`**
|
||||
Publishes an event of type `T`. Invokes all registered listeners for `T`, applying any per-listener filter. Skips if no listeners exist for `T`. Sends a diagnostic event for each invocation.
|
||||
|
||||
- **`static void Subscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class`**
|
||||
Subscribes a listener (no filter) to events of type `T`. Internally calls `Subscribe<T>(listener, null)`.
|
||||
|
||||
- **`static void Subscribe<T>(SubscriberCallbackDelegate<T> listener, Predicate<T> eventFilter) where T : class`**
|
||||
Subscribes a listener with an optional filter (`eventFilter`). The listener is invoked only if `eventFilter(eventData)` returns `true`. Registers metadata (`EventMetaData<T>`) and sends a diagnostic event.
|
||||
|
||||
- **`static void UnSubscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class`**
|
||||
Removes all subscriptions of `listener` for events of type `T`. Sends a diagnostic event.
|
||||
|
||||
- **`static void Clear()`**
|
||||
Removes *all* subscriptions for *all* event types. Sends a diagnostic event.
|
||||
|
||||
- **`static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)`**
|
||||
Registers a diagnostic listener. Sends a diagnostic event reporting the addition.
|
||||
|
||||
- **`static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)`**
|
||||
Removes a diagnostic listener. Sends a diagnostic event reporting the removal.
|
||||
|
||||
- **`static void ClearDiagnosticEvents()`**
|
||||
Removes *all* diagnostic listeners. Sends a diagnostic event.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **Type Safety**: All subscriptions and publications are strictly typed via generics (`T`). No type erasure occurs; `Subscribe<int>` and `Subscribe<string>` maintain separate listener lists.
|
||||
- **Filter Semantics**: Filters are *per-subscription* and *evaluated at publish time*. If `eventFilter == null`, the listener is always invoked.
|
||||
- **Listener Identity**: Unsubscription is based on *reference equality* of the delegate (`listener`). Two distinct delegates (even with identical implementation) are treated as different listeners.
|
||||
- **Diagnostic Consistency**: Every public mutation (`Subscribe`, `UnSubscribe`, `Publish`, `Clear`, diagnostic subscription changes) triggers exactly one `SendDiagnosticEvent` call.
|
||||
- **No Thread Safety**: The module is not thread-safe. Concurrent access to `SubscriberList` or `DiagnosticList` may cause corruption (no locking is present).
|
||||
- **Diagnostic Listener Isolation**: Diagnostic listeners do *not* receive diagnostics about their own registration/unregistration (e.g., `SubscribeToDiagnosticEvents` triggers a diagnostic, but the newly added listener does *not* receive it).
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
- **Internal Dependencies**:
|
||||
- `System` namespace (`System.Collections.Generic`, `System.Reflection`, `System`)
|
||||
- `EventDiagnosticType` enum (defined in same file)
|
||||
- `EventMetaData<T>` class (defined in same file, `internal` scope)
|
||||
- `SubscriberCallbackDelegate<T>` and `DiagnosticCallbackDelegate` delegates (defined in same file)
|
||||
|
||||
- **External Dependencies**:
|
||||
- None beyond standard .NET libraries (no external NuGet packages or framework dependencies beyond `mscorlib`).
|
||||
|
||||
- **Depended Upon**:
|
||||
- Any component in the `DataPro.Core` namespace (or referencing the assembly) may use `EventManager` to publish/subscribe to events.
|
||||
- Diagnostic consumers (e.g., logging, telemetry, debugging tools) subscribe via `SubscribeToDiagnosticEvents`.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`eventData` in `DiagnosticCallbackDelegate` may be `null`**: For subscription/unsubscription/diagnostic registration events, `eventData` is `null`. Diagnostic listeners must handle this.
|
||||
- **`listener` string may be `null`**: If `listenerMethod.DeclaringType` is `null` (e.g., static method in anonymous type), the `listener` string passed to the diagnostic callback is `null`.
|
||||
- **`Clear()` is global and destructive**: Removes *all* subscriptions across *all* event types—no selective clearing is supported.
|
||||
- **No deduplication on subscription**: Calling `Subscribe` twice with the *same* listener and filter adds *two* entries. Unsubscribing once removes *only one* entry (per `RemoveAll` logic). This may cause duplicate invocations if not managed carefully.
|
||||
- **Filter method reference in diagnostics**: When a filter is present, the diagnostic event reports `metaData.EventFilter.Method` as the listener method—*not* the callback method. This may be confusing if the filter and callback are defined in different methods.
|
||||
- **No weak references**: Listeners are held via strong references. If subscribers forget to `UnSubscribe`, they may be kept alive indefinitely (memory leak risk).
|
||||
- **Diagnostic events are synchronous and blocking**: Each diagnostic callback is invoked synchronously during `EventManager` operations. Slow diagnostic handlers will delay event publishing/subscription.
|
||||
- **`EventMetaData<T>` is internal**: Cannot be extended or inspected externally; behavior is fixed by the implementation.
|
||||
|
||||
None identified beyond the above.
|
||||
102
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/PluginLib.md
Normal file
102
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/PluginLib.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/DataPRO.Core/PluginLib/PluginConfigData.cs
|
||||
- DataPRO/DataPRO.Core/PluginLib/PluginConfig.cs
|
||||
- DataPRO/DataPRO.Core/PluginLib/PluginConfigSectionHandler.cs
|
||||
- DataPRO/DataPRO.Core/PluginLib/PluginManager.cs
|
||||
generated_at: "2026-04-16T04:27:52.597409+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "a022d6fe08f41d94"
|
||||
---
|
||||
|
||||
# PluginLib
|
||||
|
||||
## Documentation: Plugin Configuration and Management Module
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides infrastructure for managing plugins in the DataPRO system using Managed Extensibility Framework (MEF). It defines configuration structures for specifying plugin directories, a static configuration accessor (`PluginConfig`), and a singleton `PluginManager` responsible for discovering, loading, and resolving plugin assemblies from configured directories. The module enables dynamic plugin discovery and composition at runtime based on MEF exports, while enforcing strict validation of plugin folder paths and thread-safe initialization.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `PluginConfigData`
|
||||
- **`string[] PluginFolders`**
|
||||
Public field annotated with `[XmlArrayItem("Folder")]`. Holds an array of strings representing plugin folder paths, deserialized from XML configuration.
|
||||
|
||||
#### `PluginConfig`
|
||||
- **`const string DataProPlugins = "dataProPlugins"`**
|
||||
Constant key used to locate the base plugin configuration setting in app.config.
|
||||
- **`string GetDataProPluginsSetting(string setting)`**
|
||||
Concatenates the value of the `"dataProPlugins"` app setting (retrieved via `DataProConfig.GetAppSetting`) with the provided `setting`, separated by a dot (`.`). Used to construct full setting names for plugin-specific configuration.
|
||||
|
||||
#### `PluginConfigSectionHandler`
|
||||
- **`FilterHashKeyCollection HashKeys`**
|
||||
Configuration property accessor for the `"PluginFolders"` element. Returns a `FilterHashKeyCollection` containing `FilterHashElement` instances parsed from the configuration section.
|
||||
|
||||
#### `FilterHashKeyCollection`
|
||||
- **`FilterHashElement this[int idx]`**
|
||||
Indexer to access `FilterHashElement` items by zero-based index.
|
||||
- **`protected override ConfigurationElement CreateNewElement()`**
|
||||
Returns a new `FilterHashElement` instance (used internally by .NET configuration system).
|
||||
- **`protected override object GetElementKey(ConfigurationElement element)`**
|
||||
Returns the `Key` property of the given `FilterHashElement` (used for internal collection management).
|
||||
|
||||
#### `FilterHashElement`
|
||||
- **`string Key`**
|
||||
Required, key property (marked `IsKey = true`). Represents the identifier/name for the configuration entry.
|
||||
- **`string Value`**
|
||||
Optional property. Stores the associated value (e.g., a file path).
|
||||
|
||||
#### `PluginManager`
|
||||
- **`static T GetPlugin<T>() where T : class`**
|
||||
Returns a *single* MEF-exported instance of type `T`. Throws an exception (implicitly, via MEF) if zero or more than one export of type `T` exists. Returns `null` if no export is found.
|
||||
- **`static T GetPlugin<T>(string configPluginSetting) where T : class`**
|
||||
Returns a *specific* MEF-exported instance of type `T` by matching `item.Value.ToString() == configPluginSetting`. Returns `null` if no matching plugin is found.
|
||||
- **`static IEnumerable<Lazy<T>> GetPlugins<T>() where T : class`**
|
||||
Returns *all* MEF-exported instances of type `T` as `Lazy<T>` objects.
|
||||
- **`List<Assembly> GetPluginList<T>() where T : class`**
|
||||
Returns a deduplicated list of `Assembly` objects from directories in the MEF catalog that contain at least one part (plugin). *Note: This method returns after processing only the first `DirectoryCatalog` in the catalog list; subsequent catalogs are ignored.*
|
||||
- **`static PluginManager GetPluginManager()`**
|
||||
Thread-safe singleton accessor. Lazily initializes and returns the single `PluginManager` instance.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **Configuration Section Requirement**: The `"DataPro.Core.PluginLib.Config"` section *must* be present in the configuration file (`DataPro.config`). If absent, `PluginManager` constructor throws an `Exception`.
|
||||
- **Plugin Directory Validation**: Every `FilterHashElement.Value` (interpreted as a plugin directory path) *must* point to an existing directory. If any directory does not exist, `PluginManager` constructor throws an `IOException`.
|
||||
- **Thread Safety**: `PluginManager` is implemented as a singleton with lazy initialization protected by a `lock` on `ThreadLock`. All public static methods (`GetPlugin`, `GetPlugins`, `GetPluginManager`) are safe for concurrent use.
|
||||
- **Assembly Loading Scope**: Assemblies are loaded *only* from directories specified in the configuration section. No fallback to other paths occurs during initialization.
|
||||
- **MEF Composition Contract**: `GetPlugin<T>()` assumes exactly one export of type `T` exists; otherwise, MEF behavior (exception or `null`) applies. `GetPlugin<T>(string)` relies on `ToString()` of the exported instance for selection—this is fragile and not type-safe.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### *This module depends on:*
|
||||
- `System.Configuration` (for `ConfigurationSection`, `ConfigurationElement`, etc.)
|
||||
- `System.ComponentModel.Composition` (for MEF types: `AggregateCatalog`, `CompositionContainer`, `DirectoryCatalog`, `Export`, `Lazy<T>`)
|
||||
- `System.IO` (for `DirectoryInfo`, `FileInfo`, `Assembly.LoadFrom`)
|
||||
- `System.Reflection` (for `Assembly`, `AssemblyName`)
|
||||
- `DataPro.Core.Config` (specifically `DataProConfig.GetSection` and `DataProConfig.GetAppSetting`)
|
||||
|
||||
#### *This module is depended on by:*
|
||||
- Any component requiring plugin resolution (e.g., via `PluginManager.GetPlugin<T>()`).
|
||||
- Configuration infrastructure that consumes `"DataPro.Core.PluginLib.Config"` section.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`GetPluginList<T>()` is incomplete**: It returns after processing only the *first* `DirectoryCatalog` in `PluginCatalog.Catalogs`, ignoring all subsequent plugin directories. This is likely a bug.
|
||||
- **`GetPlugin<T>(string)` uses `ToString()` for selection**: Matching plugins by `item.Value.ToString()` is unreliable and not robust—plugins may not override `ToString()` meaningfully, and this approach cannot distinguish between multiple instances of the same type.
|
||||
- **Redundant assembly loading logic**: The constructor contains a loop that loads assemblies manually (`Assembly.LoadFrom`) *after* adding `DirectoryCatalog` to the `AggregateCatalog`. MEF’s `DirectoryCatalog` already loads assemblies on-demand; this manual loading is unnecessary and may cause duplicate loads or version conflicts.
|
||||
- **No error handling for assembly resolution**: The `CurrentDomain_AssemblyResolve` event handler is defined but *never subscribed* to `AppDomain.CurrentDomain.AssemblyResolve`. Dependency resolution failures will not be handled.
|
||||
- **Path handling comment is misleading**: The commented-out `IsPathRooted` check includes a typo ("absolete" instead of "absolute") and is disabled—no validation of path absoluteness occurs at runtime.
|
||||
- **`PluginConfigData` unused in runtime logic**: This class is defined but *not referenced anywhere* in the provided codebase. It appears to be a legacy or incomplete deserialization helper.
|
||||
- **No cleanup/disposal**: `PluginManager` holds unmanaged resources (`CompositionContainer`, catalogs, loaded assemblies). No `IDisposable` implementation or finalizer is present—potential memory leaks if the app domain is long-lived and plugins are reloaded.
|
||||
36
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/Properties.md
Normal file
36
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/Properties.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/DataPRO.Core/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T04:27:57.613025+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "aa0ae952c15fedf2"
|
||||
---
|
||||
|
||||
# Properties
|
||||
|
||||
## 1. Purpose
|
||||
This module (`DataPRO.Core`) is an internal .NET assembly containing core functionality for the DataPro system. Based solely on the provided source file, it serves as a foundational library with no exposed business logic—its primary documented role is to define assembly-level metadata (title, version, culture, COM visibility) and is likely consumed by other modules in the DataPro ecosystem. No executable or declarative logic beyond assembly attributes is present in this file.
|
||||
|
||||
## 2. Public Interface
|
||||
**No public types, functions, classes, or methods are defined in this file.**
|
||||
The file contains only assembly-level attributes (via `System.Reflection` and `System.Runtime.InteropServices` attributes). All content is metadata, not executable code or API surface.
|
||||
|
||||
## 3. Invariants
|
||||
- The assembly is **not visible to COM** (`ComVisible(false)`), meaning it cannot be consumed by COM clients unless explicitly overridden on individual types (none present here).
|
||||
- The assembly version is fixed at `1.0.0.0` for both `AssemblyVersion` and `AssemblyFileVersion`.
|
||||
- The `Guid` attribute uniquely identifies the typelib (`bdf5ad7a-51db-4ad0-8186-d1ead7405848`) *if* the assembly were exposed to COM (which it is not).
|
||||
- The assembly title is `"DataPro.Core"` and copyright is set to `© 2016`.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Runtime dependencies**: Requires `System.Runtime.InteropServices` and `System.Reflection` (standard .NET Framework/BCL namespaces).
|
||||
- **Consumers**: Not determinable from this file alone. As a core library, it is likely referenced by other projects in the `DataPRO` solution (e.g., `DataPRO.UI`, `DataPRO.Services`), but no explicit references are declared here.
|
||||
|
||||
## 5. Gotchas
|
||||
- **No functional logic**: This file is purely metadata and should not be used to infer business behavior or API contracts.
|
||||
- **Versioning**: The use of `AssemblyVersion("1.0.0.0")` without wildcard (`*`) means build/revisions are static—no automatic incrementing.
|
||||
- **COM compatibility**: Despite the `Guid` attribute, `ComVisible(false)` renders the typelib GUID irrelevant for actual COM interop.
|
||||
- **Missing documentation**: `AssemblyDescription` and `AssemblyCompany` are empty strings; no product or vendor details are embedded.
|
||||
- **Copyright year**: Hardcoded to 2016—may be outdated if the assembly has been maintained since.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/DataPRO.Core/ServiceManager/IServicePublishedEvent.cs
|
||||
- DataPRO/DataPRO.Core/ServiceManager/ServicePublishedEvent.cs
|
||||
- DataPRO/DataPRO.Core/ServiceManager/ServiceManager.cs
|
||||
generated_at: "2026-04-16T04:28:06.522630+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "30d34b17e2e0aff8"
|
||||
---
|
||||
|
||||
# ServiceManager
|
||||
|
||||
## Documentation: ServiceManager Module
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
The `ServiceManager` module implements a lightweight service registry pattern for managing singleton service implementations in the DataPRO core system. It enables components to publish concrete implementations of service interfaces and retrieve them later without tight coupling—publishers and consumers need not know each other’s identities. The module also emits `IServicePublishedEvent` notifications via the `EventManager` whenever a service is published or unpublished, supporting reactive service lifecycle monitoring.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `ServiceManager` (static class)
|
||||
|
||||
- **`void Publish<T>(T item) where T : class`**
|
||||
Publishes a singleton service implementation `item` for interface type `T`. Throws `ArgumentException` if `T` is already published. Fires a `ServicePublishedEvent` with `IsPublished = true`.
|
||||
|
||||
- **`void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)`**
|
||||
Publishes `item` for each interface type in `interfaceList`. If `skipPublishedInterfaces` is `false`, throws `ArgumentException` on encountering an already-published interface; otherwise, silently skips it. Fires `ServicePublishedEvent` for each *newly* published interface.
|
||||
|
||||
- **`bool Exists<T>() where T : class`**
|
||||
Returns `true` if an implementation for interface type `T` is currently published; `false` otherwise.
|
||||
|
||||
- **`bool Exists(Type t)`**
|
||||
Overload of `Exists<T>` using a runtime `Type` instance.
|
||||
|
||||
- **`T Get<T>() where T : class`**
|
||||
Returns the published implementation for interface type `T`. Throws `ArgumentException` if no implementation is published.
|
||||
|
||||
- **`void Clear<T>() where T : class`**
|
||||
Unpublishes the implementation for interface type `T`. Fires a `ServicePublishedEvent` with `IsPublished = false` before removal.
|
||||
|
||||
- **`void Clear(IEnumerable<Type> interfaceList)`**
|
||||
Unpublishes all implementations whose interface types are in `interfaceList`. Fires `ServicePublishedEvent` for each removed interface.
|
||||
|
||||
> **Note**: All methods are thread-unsafe. No synchronization is applied to the internal `Services` dictionary.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **Uniqueness per interface**: At most one implementation may be published per interface type (`Type`) at any time. Attempting to publish a second implementation for an already-published interface results in an `ArgumentException`, unless `skipPublishedInterfaces = true` in the bulk `Publish` overload.
|
||||
- **Event emission guarantee**: Every successful `Publish` or `Clear` operation (i.e., one that modifies the registry) emits exactly one `ServicePublishedEvent` via `EventManager.EventManager.Publish<IServicePublishedEvent>`.
|
||||
- **No partial failure in bulk operations**: In `Publish(object, IEnumerable<Type>, bool)`, if an exception occurs (e.g., duplicate interface with `skipPublishedInterfaces = false`), the operation is aborted, and no further interfaces in the list are processed. However, interfaces *already processed* before the failure remain published (no rollback).
|
||||
- **Event payload consistency**: The `ServicePublishedEvent.ServiceType` always matches the interface type being published/unpublished, and `IsPublished` reflects the operation direction (`true` for publish, `false` for clear).
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
- **Internal dependencies**:
|
||||
- `System.Collections.Generic.Dictionary<Type, object>` for storage.
|
||||
- `EventManager.EventManager` (from `DataPro.Core.EventManager`)—used in `SendServicePublishedEvent` to dispatch events.
|
||||
- **External dependencies**:
|
||||
- `IServicePublishedEvent` and `ServicePublishedEvent` (defined in the same `DataPro.Core.ServiceManager` namespace).
|
||||
- `System.Type` for interface identification.
|
||||
|
||||
- **Depended upon by**:
|
||||
- Components that need to register or resolve singleton services (e.g., UI modules, data providers).
|
||||
- Event subscribers listening to `IServicePublishedEvent` for service lifecycle tracking.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **No support for multiple implementations per interface**: The registry strictly enforces one implementation per interface. Overriding a service requires explicit `Clear<T>()` first.
|
||||
- **No null-check on `item` in `Publish<T>`**: Passing `null` as `item` will succeed (and store `null` in the dictionary), leading to a `NullReferenceException` on subsequent `Get<T>()` calls. Consider adding validation if nulls are undesirable.
|
||||
- **Bulk `Publish` does not validate `item` implements all requested interfaces**: If `item` does not actually implement one or more types in `interfaceList`, the dictionary stores the reference, but `Get<T>()` for that interface will return `null` (via `as T`), potentially causing runtime errors later.
|
||||
- **No thread safety**: Concurrent calls to `Publish`, `Get`, or `Clear` may corrupt the internal dictionary or cause race conditions (e.g., two threads publishing the same interface may both succeed before the duplicate check completes).
|
||||
- **Event emission is synchronous**: `SendServicePublishedEvent` calls `EventManager.EventManager.Publish`, which may block the caller until all event handlers complete. Long-running handlers could impact performance.
|
||||
- **No versioning or deprecation support**: Once a service is published, there is no mechanism to signal obsolescence or migration paths.
|
||||
|
||||
> **None identified from source alone.**
|
||||
*(Note: The above gotchas are inferred from code structure and behavior—not assumptions.)*
|
||||
205
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/Settings.md
Normal file
205
enriched-qwen3-coder-next/DataPRO/DataPRO.Core/Settings.md
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/DataPRO.Core/Settings/SettingsChangedEventArgs.cs
|
||||
- DataPRO/DataPRO.Core/Settings/SettingsCollection.cs
|
||||
generated_at: "2026-04-16T04:27:33.942396+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "d5502ead5db3d623"
|
||||
---
|
||||
|
||||
# `SettingsCollection<TKey, TItem>` Module Documentation
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
The `SettingsCollection<TKey, TItem>` class provides a dictionary-based collection that notifies subscribers of changes (add, remove, modify, clear) via the `CollectionItemPropertyChanged` event. It extends `IDictionary<TKey, TItem>` to offer standard dictionary operations while adding reactive behavior for UI binding or state synchronization scenarios. This module exists to decouple state mutation from side-effect logic (e.g., persistence, UI updates) by enabling consumers to subscribe to change events rather than manually tracking mutations.
|
||||
|
||||
---
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `SettingsCollection<TKey, TItem> : IDictionary<TKey, TItem>`
|
||||
|
||||
#### Event
|
||||
|
||||
- **`CollectionItemPropertyChanged`**
|
||||
`event EventHandler<SettingsChangedEventArgs<TKey, TItem>>`
|
||||
Fired whenever an item is added, removed, modified, or the collection is cleared.
|
||||
|
||||
#### Properties (from `IDictionary<TKey, TItem>`)
|
||||
|
||||
- **`this[TKey key]`**
|
||||
`TItem this[TKey key] { get; set; }`
|
||||
Gets or sets the value for the specified `key`. Setting a value fires a `Modified` event (note: *incorrectly* fires `Add` per implementation—see *Gotchas*).
|
||||
|
||||
- **`Keys`**
|
||||
`ICollection<TKey> Keys { get; }`
|
||||
Returns the collection of keys.
|
||||
|
||||
- **`Values`**
|
||||
`ICollection<TItem> Values { get; }`
|
||||
Returns the collection of values.
|
||||
|
||||
- **`Count`**
|
||||
`int Count { get; }`
|
||||
Returns the number of key-value pairs.
|
||||
|
||||
- **`IsReadOnly`**
|
||||
`bool IsReadOnly { get; }`
|
||||
Always `false`.
|
||||
|
||||
#### Methods (from `IDictionary<TKey, TItem>`)
|
||||
|
||||
- **`Add(TKey key, TItem value)`**
|
||||
Adds a key-value pair. Fires `CollectionItemPropertyChanged` with `ChangeSettingType.Add`.
|
||||
|
||||
- **`Add(KeyValuePair<TKey, TItem> item)`**
|
||||
Adds a key-value pair. Fires `CollectionItemPropertyChanged` with `ChangeSettingType.Add`.
|
||||
|
||||
- **`Remove(TKey key)`**
|
||||
Removes the entry with the specified `key`. Returns `true` if removed. Fires `CollectionItemPropertyChanged` with `ChangeSettingType.Remove`.
|
||||
|
||||
- **`Remove(KeyValuePair<TKey, TItem> item)`**
|
||||
Removes the entry matching the key of `item`. Returns `true` if removed. Fires `CollectionItemPropertyChanged` with `ChangeSettingType.Remove`.
|
||||
|
||||
- **`Clear()`**
|
||||
Removes all entries. Fires `CollectionItemPropertyChanged` with `ChangeSettingType.ClearAll`.
|
||||
|
||||
- **`ContainsKey(TKey key)`**
|
||||
`bool ContainsKey(TKey key)`
|
||||
Returns `true` if `key` exists.
|
||||
|
||||
- **`Contains(KeyValuePair<TKey, TItem> item)`**
|
||||
`bool Contains(KeyValuePair<TKey, TItem> item)`
|
||||
Returns `true` if both key and value exist in the collection.
|
||||
|
||||
- **`TryGetValue(TKey key, out TItem value)`**
|
||||
`bool TryGetValue(TKey key, out TItem value)`
|
||||
Returns `true` and sets `value` if `key` exists.
|
||||
|
||||
- **`CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)`**
|
||||
Throws `NotImplementedException`.
|
||||
|
||||
- **`GetEnumerator()`**
|
||||
`IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()`
|
||||
Returns an enumerator over the collection.
|
||||
|
||||
- **`IEnumerable.GetEnumerator()`**
|
||||
Explicit implementation of `IEnumerable.GetEnumerator()`.
|
||||
|
||||
---
|
||||
|
||||
### `SettingsChangedEventArgs<TKey, TItem> : EventArgs`
|
||||
|
||||
#### Constructors
|
||||
|
||||
- **`SettingsChangedEventArgs(ChangeSettingType changeType)`**
|
||||
Initializes with only the `ChangeType`.
|
||||
|
||||
- **`SettingsChangedEventArgs(ChangeSettingType changeType, TKey key)`**
|
||||
Initializes with `ChangeType` and `Key`.
|
||||
|
||||
- **`SettingsChangedEventArgs(ChangeSettingType changeType, TKey key, TItem item)`**
|
||||
Initializes with `ChangeType`, `Key`, and `Item`.
|
||||
|
||||
#### Properties
|
||||
|
||||
- **`ChangeType`**
|
||||
`ChangeSettingType ChangeType { get; }`
|
||||
Type of change (`Add`, `Remove`, `Modified`, or `ClearAll`).
|
||||
|
||||
- **`Key`**
|
||||
`TKey Key { get; }`
|
||||
Key associated with the change (may be default if `ClearAll`).
|
||||
|
||||
- **`Item`**
|
||||
`TItem Item { get; }`
|
||||
Value associated with the change (may be default if `Remove` or `ClearAll`).
|
||||
|
||||
---
|
||||
|
||||
### `ChangeSettingType` Enum
|
||||
|
||||
- **`Add = 0`**
|
||||
A new item was added.
|
||||
|
||||
- **`Remove = 1`**
|
||||
An item was removed.
|
||||
|
||||
- **`Modified = 3`**
|
||||
An existing item’s value was updated.
|
||||
|
||||
- **`ClearAll = 4`**
|
||||
The entire collection was cleared.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Event Firing**:
|
||||
- `Add`, `Remove`, and `ClearAll` always fire an event.
|
||||
- `this[key] = value` *always* fires an event (with `ChangeType.Add`, per implementation—see *Gotchas*).
|
||||
- Events are fired *after* the underlying dictionary is mutated (i.e., state is consistent at event time).
|
||||
|
||||
- **Event Arguments**:
|
||||
- For `Add`/`Modified`: `Key` and `Item` are non-null/non-default (assuming `TKey`/`TItem` allow it); `ChangeType` is `Add`.
|
||||
- For `Remove`: `Item` is default (`default(TItem)`); `ChangeType` is `Remove`.
|
||||
- For `ClearAll`: `Key` and `Item` are default; `ChangeType` is `ClearAll`.
|
||||
|
||||
- **No Partial Updates**:
|
||||
Only full additions, removals, or clears trigger events—no partial or batched updates.
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`System.Collections.Generic`**
|
||||
Provides `Dictionary<TKey, TItem>`, `ICollection<TKey>`, `ICollection<TItem>`, `IEnumerator<T>`, `IDictionary<TKey, TItem>`.
|
||||
- **`System`**
|
||||
Provides `EventArgs`, `EventHandler<T>`, `NotImplementedException`, `enum`.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **`DataPRO.Core.Settings` namespace**
|
||||
Used internally by consumers (e.g., `SettingsChangedEventArgs` and `ChangeSettingType` are public and likely used elsewhere in the codebase to handle settings changes).
|
||||
|
||||
### Inferred Usage:
|
||||
- Likely consumed by UI layers or configuration managers that need to react to settings changes (e.g., saving to disk, updating UI controls).
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Incorrect `Modified` Event Type**:
|
||||
The indexer setter (`this[TKey key] { set { ... } }`) fires `ChangeSettingType.Add` instead of `ChangeSettingType.Modified`. This is inconsistent with the semantic meaning of "modify" and may mislead consumers expecting `Modified` for updates.
|
||||
**Example**:
|
||||
```csharp
|
||||
collection["foo"] = "bar"; // Fires Add, not Modified
|
||||
```
|
||||
|
||||
- **`CopyTo` Not Implemented**:
|
||||
`CopyTo(KeyValuePair<TKey, TItem>[], int)` throws `NotImplementedException`. This violates the `ICollection<KeyValuePair<TKey, TItem>>` contract and may cause runtime failures if used (e.g., via LINQ’s `ToArray()` or `ToList()`).
|
||||
|
||||
- **`Contains(KeyValuePair<TKey, TItem>)` Semantics**:
|
||||
Checks both key *and* value equality. This is stricter than typical dictionary `Contains` behavior (which usually checks only key), and may cause confusion.
|
||||
|
||||
- **No Validation on Keys/Values**:
|
||||
No checks for `null` keys (if `TKey` is a reference type) or duplicate keys—relies on underlying `Dictionary<TKey, TItem>` to throw `ArgumentNullException`/`ArgumentException`.
|
||||
|
||||
- **No Thread Safety**:
|
||||
No synchronization primitives are used. Concurrent access may corrupt state or cause race conditions in event firing.
|
||||
|
||||
- **Event Subscribers May Receive Unexpected `Item` Values**:
|
||||
For `Remove` and `ClearAll`, `Item` is `default(TItem)`. Consumers must not assume `Item` is always meaningful.
|
||||
|
||||
- **No `Modified` Event for Direct Assignment**:
|
||||
Since the indexer uses `Add` semantics, there is no way to distinguish between *adding a new key* and *updating an existing key* via the event—unless the consumer tracks state themselves.
|
||||
|
||||
- **Historical Quirk**:
|
||||
The `ClearAll` event omits `Key` and `Item` (both `default`), while other operations populate them. This is consistent with the enum design but may require special handling in event handlers.
|
||||
|
||||
---
|
||||
|
||||
*Documentation generated from source files only. No external behavior or assumptions beyond the provided code.*
|
||||
Reference in New Issue
Block a user