Files
2026-04-17 14:55:32 -04:00

5.5 KiB

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common.Core/ServiceManager/IServicePublishedEvent.cs
Common/DTS.Common.Core/ServiceManager/ServicePublishedEvent.cs
Common/DTS.Common.Core/ServiceManager/ServiceManager.cs
2026-04-16T11:43:09.898125+00:00 zai-org/GLM-5-FP8 1 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.