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

5.1 KiB
Raw Permalink Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.CommonCore/ModuleCatalog/AggregateModuleCatalog.cs
2026-04-16T02:14:07.054648+00:00 Qwen/Qwen3-Coder-Next-FP8 1 6c5b3cbd6c5102fe

ModuleCatalog

Documentation: AggregateModuleCatalog

1. Purpose

AggregateModuleCatalog is a composite implementation of IModuleCatalog that aggregates multiple underlying module catalogs into a unified interface for module discovery and dependency resolution within the Prism-based modularity framework. It enables the system to support heterogeneous module sources (e.g., ModuleCatalog, DirectoryModuleCatalog, custom catalogs) by delegating operations to the appropriate catalog while presenting a single, flat view of all modules. It is initialized with a default ModuleCatalog instance, ensuring at least one catalog is always present for module registration.

2. Public Interface

  • AggregateModuleCatalog()
    Constructor. Initializes a new instance with a single internal ModuleCatalog instance added to _catalogs. No parameters.

  • void AddCatalog(IModuleCatalog catalog)
    Adds a new IModuleCatalog instance to the internal _catalogs list. Throws ArgumentNullException if catalog is null. No validation is performed on catalog type or compatibility (commented-out logic suggests past intent for such checks, but it is inactive).

  • IEnumerable<ModuleInfo> Modules { get; }
    Returns a flattened enumeration of all ModuleInfo instances across all internal catalogs, via SelectMany.

  • IEnumerable<ModuleInfo> GetDependentModules(ModuleInfo moduleInfo)
    Returns the dependencies of moduleInfo. Throws InvalidOperationException if moduleInfo is not contained in exactly one internal catalog (due to use of .Single()). Delegates to the containing catalogs GetDependentModules.

  • IEnumerable<ModuleInfo> CompleteListWithDependencies(IEnumerable<ModuleInfo> modules)
    Returns modules plus all transitive dependencies. Groups modules by the single catalog that contains each module (throws InvalidOperationException if a module is missing or duplicated across catalogs), then delegates CompleteListWithDependencies per catalog and flattens results.

  • void Initialize()
    Calls Initialize() on each internal catalog in sequence.

  • void AddModule(ModuleInfo moduleInfo)
    Adds moduleInfo exclusively to the first catalog in _catalogs (i.e., the default ModuleCatalog created in the constructor). Does not attempt to distribute or search for an appropriate catalog.

3. Invariants

  • _catalogs always contains at least one catalog (initialized to a new ModuleCatalog in the constructor).
  • AddModule always targets _catalogs[0]; other catalogs are not modified by this method.
  • GetDependentModules and CompleteListWithDependencies assume each ModuleInfo belongs to exactly one catalog. If a ModuleInfo appears in multiple catalogs or none, these methods throw InvalidOperationException (from .Single()).
  • Catalogs is read-only (via AsReadOnly()), but _catalogs itself is mutable via AddCatalog.

4. Dependencies

  • Depends on:

    • Microsoft.Practices.Prism.Modularity (specifically IModuleCatalog, ModuleInfo).
    • Standard .NET libraries: System, System.Collections.Generic, System.Linq.
  • Depended on by:

    • Not evident from this file alone. Likely consumed by Prisms module initialization infrastructure (e.g., ModuleManager, ModuleInitializer) or custom bootstrappers in the DTS codebase.

5. Gotchas

  • Critical ambiguity in AddModule behavior: It silently routes all module additions to the first catalog, ignoring others. This may lead to modules being registered in an unintended catalog if the caller assumes uniform distribution or catalog-specific registration.
  • Fragile catalog lookup: Both GetDependentModules and CompleteListWithDependencies use .Single(x => x.Modules.Contains(moduleInfo)), which assumes uniqueness of ModuleInfo across catalogs. If the same ModuleInfo instance (by reference or identity) appears in multiple catalogs—or is missing—these methods will throw at runtime.
  • No validation in AddCatalog: Despite commented-out logic, no checks prevent adding duplicate catalog types (e.g., two DirectoryModuleCatalogs) or incompatible catalogs. This may cause unexpected behavior (e.g., duplicate modules, conflicting paths).
  • No thread-safety: The internal _catalogs list is modified by AddCatalog and AddModule without synchronization. Concurrent access may cause race conditions.
  • No documentation on catalog ordering semantics: The order of catalogs in _catalogs may affect behavior (e.g., AddModule targets index 0; Modules enumeration order is catalog-order-dependent), but no guarantees or documentation are provided.
  • Commented-out code: The commented-out logic in AddCatalog suggests unresolved design questions about catalog compatibility (e.g., path handling for DirectoryModuleCatalog), indicating potential technical debt or incomplete feature implementation.