6.3 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | |||
|---|---|---|---|---|---|---|---|
|
2026-04-16T02:06:21.064356+00:00 | Qwen/Qwen3-Coder-Next-FP8 | 1 | a01f75e5b963dd9f |
ServiceManager
Documentation: ServiceManager Module
1. Purpose
The ServiceManager module provides a centralized registry for singleton service implementations, enabling decoupled service discovery and lifecycle management. Components can publish implementations of service interfaces (e.g., IMyService) and other components can retrieve them by interface type without knowledge of the concrete publisher. It also emits IServicePublishedEvent notifications via EventManager whenever services are published or unpublished, supporting reactive integration patterns.
2. Public Interface
ServiceManager (static class)
-
void Publish<T>(T item) where T : class
Publishes a singleton service implementationitemfor interface typeT. ThrowsArgumentExceptionifTis already published. Fires aServicePublishedEventwithIsPublished = true. -
void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)
Publishesitemfor each interface type ininterfaceList. IfskipPublishedInterfacesisfalse, throwsArgumentExceptionon encountering an already-published interface; otherwise, skips it. FiresServicePublishedEventfor newly published interfaces. -
bool Exists<T>() where T : class
Returnstrueif interface typeThas a published service;falseotherwise. -
bool Exists(Type t)
Returnstrueif interface typethas a published service;falseotherwise. -
T Get<T>() where T : class
Returns the published service instance for interface typeT. ThrowsArgumentExceptionifTis not published. -
void Clear<T>() where T : class
Unpublishes the service for interface typeT. Fires aServicePublishedEventwithIsPublished = falsebefore removal. No-op ifTis not published. -
void Clear(IEnumerable<Type> interfaceList)
Unpublishes services for all interface types ininterfaceList. FiresServicePublishedEventwithIsPublished = falsefor each successfully removed service.
IServicePublishedEvent (interface)
-
Type ServiceType { get; }
Read-only property returning theTypeof the service interface being published/unpublished. -
bool IsPublished { get; }
Read-only property:trueif the event indicates publication;falseif unpublishing.
ServicePublishedEvent (class)
-
Type ServiceType { get; internal set; }
Gets or sets (internally) the service interfaceType. -
bool IsPublished { get; internal set; }
Gets or sets (internally) the publication status.
3. Invariants
- Uniqueness per interface: Each interface type
Tmay have at most one published service instance. Attempting to publish a second implementation for the same interface throwsArgumentException(unlessskipPublishedInterfaces = truein the bulkPublishoverload). - Consistency of
Exists/Get/Clear:Exists<T>()andExists(Type)returntrueif and only ifServices.ContainsKey(typeof(T))istrue.Get<T>()will throw ifExists<T>()isfalse. - Event emission order: For
Publish/Clearoperations, theServicePublishedEventis fired before the service is added/removed from the internal dictionary. Specifically:Publish→Services.Add(...)→SendServicePublishedEvent(...)Clear→SendServicePublishedEvent(...)→Services.Remove(...)
- No null services: The
Servicesdictionary stores only non-null references.Publishaccepts anyclass, but the dictionary does not explicitly validate non-nullability beyond standard dictionary behavior.
4. Dependencies
-
Internal dependencies:
System.Collections.Generic.Dictionary<Type, object>for service storage.EventManager.EventManager(fromDTS.Common.Corenamespace) to publishIServicePublishedEventinstances viaEventManager.EventManager.Publish<IServicePublishedEvent>(...).
-
External dependencies:
System(forType,ArgumentException,IEnumerable<T>, etc.).
-
Depended upon by:
- Any component requiring service discovery (e.g., via
ServiceManager.Get<T>()). - Event subscribers listening for
IServicePublishedEventto react to service lifecycle changes.
- Any component requiring service discovery (e.g., via
5. Gotchas
- No thread-safety guarantees: The
Servicesdictionary is not thread-safe. ConcurrentPublish/Clear/Getcalls may cause race conditions or exceptions (e.g.,InvalidOperationExceptionduring enumeration or dictionary mutation). Publish(object, ...)allows multiple interfaces per instance: The same object instance may be published under multiple interface types, but this is not validated beyond the existence check per interface.Get<T>()usesas Tcast: If the stored object is not actually assignable toT(e.g., due to type mismatch or casting issues),Get<T>()returnsnullwithout throwing—but only if the key exists. However, the current implementation first checksContainsKey, sonullreturn is impossible if the stored object is non-null and correctly typed. If the stored object isnull,ContainsKeywould still betrue, andGet<T>()would returnnull. This edge case is not explicitly guarded against.- Event emission timing: Subscribers receive
ServicePublishedEventbefore the service is available (forPublish) or after it is removed (forClear). This may cause race conditions if subscribers immediately callGet<T>()—they will succeed forPublish, but fail forClear. - No support for service versioning or replacement: Once published, a service cannot be replaced without explicit
Clear<T>()followed byPublish<T>(). internal setonServicePublishedEventproperties: While the properties are public, their setters areinternal, meaning only code within the same assembly can construct/modifyServicePublishedEventinstances. This is consistent with the design but limits extensibility.
None identified beyond the above.