7.5 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | ||||
|---|---|---|---|---|---|---|---|---|
|
2026-04-16T11:42:06.536831+00:00 | zai-org/GLM-5-FP8 | 1 | 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
-
Singleton Pattern:
_pluginManageris a static singleton; once initialized, subsequent calls toGetPluginManagerreturn the existing instance regardless of theappPathparameter passed. -
Thread Safety: All access to the singleton initialization is protected by
THREAD_LOCKobject. -
Configuration Requirement: The configuration section
"DTS.Common.Core.PluginLib.Config"must exist in the application configuration file, or thePluginManagerconstructor throws anException. -
Directory Existence: All plugin directories specified in
FilterHashElement.Valuemust exist at initialization time, or anIOExceptionis thrown. -
Assembly Exclusion: Assemblies with names starting with
"DTS.Common","C1", or"Xceed"are explicitly excluded from manual assembly loading in the constructor. -
MEF Export Uniqueness:
GetPlugin<T>()(the parameterless overload) expects exactly zero or one export of typeT; MEF throws an exception if multiple exports exist.
4. Dependencies
This module depends on:
DTS.Common.Core.Config- ForDTSConfig.GetSection(),DTSConfig.GetAppSetting(), andDTSConfig.DTSConfigInit()DTS.Common.Utilities.Logging- ForAPILogger.Log()static methodSystem.ComponentModel.Composition.Hosting- MEF container and catalog typesSystem.ComponentModel.Composition.ReflectionModel- ForReflectionModelServices.GetPartType()System.Configuration- For configuration section infrastructureSystem.Xml.Serialization- ForPluginConfigDataXML serialization
Consumers:
- Any module requiring plugin extensibility via MEF exports
- Code calling
PluginManager.GetPlugin<T>()orPluginManager.GetPlugins<T>()
5. Gotchas
-
Unused Assembly Resolve Handler: The method
CurrentDomain_AssemblyResolveis defined but never wired up toAppDomain.CurrentDomain.AssemblyResolve. It will never be called unless external code attaches it. -
Configuration Section Name Inconsistency:
PluginConfigDatais decorated with[XmlRoot(ElementName = "DatPro.Core.PluginLib.Config")](legacy "DatPro" naming), whilePluginManagerlooks for"DTS.Common.Core.PluginLib.Config". These are different section names;PluginConfigDataappears to be legacy/unused code. -
Unused Parameter in GetPluginList: The generic type parameter
TinGetPluginList<T>()is declared but never used in the method body. The method returns all assemblies regardless of type. -
Dead Code Before Lock: In
GetPluginManager(), aDirectoryInfoobject is created fromappPathbefore the lock but never used:if (!string.IsNullOrWhiteSpace(appPath)) { var directoryInfo = new DirectoryInfo(appPath); } -
Empty Loop Bodies: The singleton check contains loops with empty bodies:
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.
-
Plugin Matching via ToString():
GetPlugin<T>(string configPluginSetting)matches plugins by comparingitem.Value.ToString()toconfigPluginSetting. This relies on the plugin'sToString()override returning a meaningful identifier. -
Null Return Possible:
GetPlugin<T>()returnsnullif no export is found, not an exception. Callers must handle null. -
Hardcoded Assembly Exclusions: The exclusion list (
"DTS.Common","C1","Xceed") is hardcoded in the constructor and not configurable.