Source of truth (2026)
  • DataManagementEngineStandard/AssemblyHandler/AssemblySystem/AssemblyHandler.Core.cs
  • .../AssemblyHandler.Loaders.cs | .Scanning.cs | .Helpers.cs
  • .../AssemblyHandler.NuGetOperations.cs | .NuGetSources.cs
  • .../AssemblyHandler.DriverTracking.cs | .Statistics.cs
  • DataManagementEngineStandard/AssemblyHandler/PluginSystem/SharedContextAssemblyHandler.cs

API Snapshot

public interface IAssemblyHandler : IDisposable
{
    List<assemblies_rep> Assemblies { get; set; }
    List<Assembly> LoadedAssemblies { get; set; }
    List<Type> LoaderExtensions { get; set; }
    List<AssemblyClassDefinition> LoaderExtensionClasses { get; set; }
    List<ILoaderExtention> LoaderExtensionInstances { get; set; }
    List<AssemblyClassDefinition> DataSourcesClasses { get; set; }

    // Loading
    Assembly LoadAssembly(string path);
    string LoadAssembly(string path, FolderFileTypes fileTypes);
    IErrorsInfo LoadAllAssembly(IProgress<PassedArgs> progress, CancellationToken token);
    List<Assembly> LoadAssembliesFromFolder(string folderPath,
        FolderFileTypes folderFileType, bool scanForDataSources = true);

    // NuGet
    Task<List<NuGetSearchResult>> SearchNuGetPackagesAsync(string searchTerm,
        int skip = 0, int take = 20, bool includePrerelease = false,
        CancellationToken token = default);
    Task<List<string>> GetNuGetPackageVersionsAsync(string packageId,
        bool includePrerelease = false, CancellationToken token = default);
    Task<List<Assembly>> LoadNuggetFromNuGetAsync(string packageName,
        string version = null, IEnumerable<string> sources = null);

    // NuGet Sources
    List<NuGetSourceConfig> GetNuGetSources();
    void AddNuGetSource(string name, string url, bool isEnabled = true);
    void RemoveNuGetSource(string name);
    List<string> GetActiveSourceUrls();

    // Driver Tracking
    void TrackDriverPackage(string packageId, string version,
        string driverClassName, DataSourceType dsType);
    List<DriverPackageMapping> GetAllDriverPackageMappings();
    bool IsDriverFromNuGet(string driverClassName);

    // Statistics
    AssemblyLoadStatistics GetLoadStatistics();
}

DLL Loading & Scanning

Full Scan Flow

IAssemblyHandler handler = dmeEditor.assemblyHandler;

// Full discovery pass
await Task.Run(() => handler.LoadAllAssembly(progress, token));

// Targeted single DLL
var asm = handler.LoadAssembly(@"Plugins\MySourcePlugin.dll");

// Folder scan
var assemblies = handler.LoadAssembliesFromFolder(
    @"Plugins", FolderFileTypes.DataSources, scanForDataSources: true);

Load Sequence

  1. Runtime loading — Load built-in assemblies from current app domain
  2. Extension discovery — Find and instantiate ILoaderExtention implementations
  3. Folder loading — Scan configured directories for plugins
  4. Driver scanning — Discover IDataSource and driver classes
  5. Extension scans — Run each ILoaderExtention.Scan()

FolderFileTypes

TypeDirectory
DataSourcesProjectClasses/
AddinsAddin/
ConnectionDriversConnectionDrivers/
LoadingExtensionsLoadingExtensions/
OtherDLLOtherDLL/
AIAI/
ScriptsScripts/

NuGet Management

// Search
var packages = await handler.SearchNuGetPackagesAsync("postgres", take: 10);

// Versions
var versions = await handler.GetNuGetPackageVersionsAsync("Npgsql");

// Sources
handler.AddNuGetSource("my-feed", "https://my-feed/v3/index.json");
var sources = handler.GetActiveSourceUrls();
handler.RemoveNuGetSource("old-feed");

// Load from NuGet
var loaded = await handler.LoadNuggetFromNuGetAsync(
    "MyCompany.CustomDataSource",
    version: versions.First());

// Persistence files
// nuget_sources.json    — source list and enabled flags
// driver_packages.json  — driver to package/version mapping

Driver Package Tracking

Tracks which NuGet packages provide which drivers for provenance and security audit:

// Track a driver's package origin
handler.TrackDriverPackage(
    packageId: "TheTechIdea.Beep.DataSources.SQLite",
    version: "2.0.0",
    driverClassName: "SQLiteDataSource",
    dsType: DataSourceType.SqlLite);

// Query mappings
var mappings = handler.GetAllDriverPackageMappings();
foreach (var m in mappings)
    Console.WriteLine($"{m.DriverClassName} ← {m.PackageId} v{m.Version}");

// Check origin
bool fromNuGet = handler.IsDriverFromNuGet("SQLiteDataSource");

// Persisted to: driver_packages.json
// Automatically loaded on startup

DriverPackageMapping

PropertyDescription
PackageIdNuGet package ID
VersionInstalled version
DriverClassNameFull class name of the driver
DataSourceTypeType of data source
InstalledDateWhen the package was installed

Load Statistics

AssemblyHandler tracks loading performance and outcomes:

public class AssemblyLoadStatistics
{
    public int TotalAssembliesLoaded { get; set; }
    public TimeSpan TotalLoadTime { get; set; }
    public DateTime LastLoadTimestamp { get; set; }
    public int DriversFound { get; set; }
    public int DataSourcesFound { get; set; }
    public Dictionary<string, int> AssembliesByFolderType { get; set; }
}

// Get statistics after loading
var stats = handler.GetLoadStatistics();
Console.WriteLine($"Assemblies: {stats.TotalAssembliesLoaded}");
Console.WriteLine($"Load time: {stats.TotalLoadTime.TotalSeconds:F2}s");
Console.WriteLine($"Drivers: {stats.DriversFound}");
Console.WriteLine($"Data sources: {stats.DataSourcesFound}");

foreach (var (folder, count) in stats.AssembliesByFolderType)
    Console.WriteLine($"  {folder}: {count}");

Custom Loader Extensions

public sealed class CustomLoaderExtension : ILoaderExtention
{
    private readonly AssemblyHandler _handler;
    private readonly IConfigEditor _config;

    public CustomLoaderExtension(AssemblyHandler handler)
    {
        _handler = handler;
        _config = handler.ConfigEditor;
    }

    public IErrorsInfo LoadAllAssembly()
    {
        return _handler.ErrorObject;
    }

    public IErrorsInfo Scan(assemblies_rep assembly)
    {
        if (assembly?.DllLib != null) return Scan(assembly.DllLib);
        return _handler.ErrorObject;
    }

    public IErrorsInfo Scan(Assembly assembly)
    {
        foreach (var type in assembly.GetTypes())
        {
            if (type.GetInterfaces().Contains(typeof(IDataSource)))
            {
                var cls = _handler.GetAssemblyClassDefinition(
                    type.GetTypeInfo(), "IDataSource");
                _config.DataSourcesClasses.Add(cls);
            }
        }
        return _handler.ErrorObject;
    }

    public IErrorsInfo Scan()
    {
        foreach (var asm in _handler.LoadedAssemblies)
            Scan(asm);
        return _handler.ErrorObject;
    }
}
Contract name is ILoaderExtention

The current interface spelling in the codebase is ILoaderExtention (not ILoaderExtension).

Scanned Data Contracts

During AssemblyHandler.ScanAssembly(), the handler checks these contracts and registers metadata in ConfigEditor:

// Contracts scanned by ProcessTypeInfo():
IDataSource, ILoaderExtention, IWorkFlowAction, IDM_Addin,
IWorkFlowStep, IBeepViewModel, IWorkFlowEditor, IRule,
IRuleParser, IFunctionExtension, IPrintManager, IAddinVisSchema,
IPipelinePlugin, IFileFormatReader, IDefaultValueResolver

SharedContextAssemblyHandler vs AssemblyHandler

SharedContextAssemblyHandler (2,568 lines) is a modern replacement for AssemblyHandler (267 lines) that uses SharedContextManager as the core loading system. Both implement IAssemblyHandler.

Architectural Comparison

AspectAssemblyHandlerSharedContextAssemblyHandler
Core engineDirect Assembly.LoadFromSharedContextManager with AssemblyLoadContext isolation
Plugin discoveryManual type scanning (ScanAllAssemblies)IScanningService abstraction + AssemblyScanningAssistant
Driver handlingBuilt into scanningDedicated DriverDiscoveryAssistant
Plugin registryNone — manual registration via ConfigEditorPluginRegistry for centralized plugin tracking
Plugin installationNone — NuGet integrated directlyPluginInstaller for NuGet → extract → register pipeline
Plugin lifecycleNone — load onlyPluginLifecycleManager: Load → Init → Execute → Unload
Plugin healthNonePluginHealthMonitor: heartbeat, timeout, auto-restart
IsolationAll in default AssemblyLoadContextPluginIsolationManager: per-plugin ALC when needed
Version mgmtNonePluginVersionManager: dependency resolution, compat checks
Plugin messagingNonePluginMessageBus: in-process pub/sub
Out-of-processNonePluginProcessManager: IPC-based plugin hosting
Assembly trackingManual listsSharedAssemblyTracker: shared vs isolated context tracking
Unload safetyNo analysisUnloadAnalysis: dependency chain check before unload
DoNET isolationNoPreferDefaultContextDependencies: checks AssemblyLoadContext.Default first
NuGetIntegrated into handlerNuGetPackageManager + NuggetPackageDownloader + NuggetManager
Creating instancesManual Activator.CreateInstanceInstanceCreationAssistant: DI-aware instantiation

When to Use Each

ScenarioHandlerReason
Single app, few static pluginsAssemblyHandlerSimpler, no overhead. Direct Assembly.LoadFrom is sufficient.
Multi-tenant, many pluginsSharedContextAssemblyHandlerShared ALC reduces memory; PluginRegistry centralizes tracking.
Plugins that need unloadingSharedContextAssemblyHandlerALC isolation enables clean unload; UnloadAnalysis prevents dangling refs.
Plugin health monitoringSharedContextAssemblyHandlerHeartbeat + timeout + auto-restart via PluginHealthMonitor.
NuGet-heavy plugin loadingSharedContextAssemblyHandlerPluginInstaller pipeline: NuGet → extract → scan → register → init.
Version conflict resolutionSharedContextAssemblyHandlerPer-plugin ALC allows different versions of same dependency.
Out-of-process pluginsSharedContextAssemblyHandlerPluginProcessManager provides IPC isolation for untrusted code.
Inter-plugin communicationSharedContextAssemblyHandlerPluginMessageBus enables decoupled pub/sub between plugins.

Configuration

// Via BeepService
var service = new BeepService();
service.AssemblyHandlerType = AssemblyHandlerType.SharedContext;
service.Configure(path, "MyApp", BeepConfigType.Application);

// Direct construction
var handler = new SharedContextAssemblyHandler(
    configEditor, errorObject, logger, util);

// Plugin pipeline
handler.PluginInstaller.InstallFromNuGetAsync("MyPlugin", "1.0.0");
handler.PluginRegistry.Discover();
handler.PluginLifecycleManager.InitializeAll();
handler.PluginHealthMonitor.Start();

Usage Examples

Complete Startup

var handler = editor.assemblyHandler;

// Load all assemblies with progress
var progress = new Progress<PassedArgs>(args =>
    Console.WriteLine($"[{args.ParameterInt1}%] {args.Messege}"));

handler.LoadAllAssembly(progress, CancellationToken.None);

// Check results
var stats = handler.GetLoadStatistics();
Console.WriteLine($"Loaded {stats.TotalAssembliesLoaded} assemblies " +
    $"in {stats.TotalLoadTime.TotalSeconds:F1}s");
Console.WriteLine($"Found {stats.DataSourcesFound} data sources, " +
    $"{stats.DriversFound} drivers");

NuGet Driver Installation

// Search for PostgreSQL driver
var packages = await handler.SearchNuGetPackagesAsync("postgresql", take: 5);

// Get latest version
var version = (await handler.GetNuGetPackageVersionsAsync(
    packages[0].PackageId)).First();

// Install and load
var assemblies = await handler.LoadNuggetFromNuGetAsync(
    packages[0].PackageId, version);

// Track provenance
handler.TrackDriverPackage(
    packages[0].PackageId, version,
    "PostgreDataSource", DataSourceType.Postgresql);

Error Handling

var result = handler.LoadAllAssembly(progress, token);

if (result.Flag != Errors.Ok)
{
    Console.WriteLine($"Load failed: {result.Message}");
    if (result.Ex != null)
        Console.WriteLine($"Exception: {result.Ex.Message}");
}

// Check for load errors
if (handler.HasLoadErrors)
{
    foreach (var error in handler.LoadErrors)
        Console.WriteLine($"Load Error: {error}");
}

Complete Source File Map (31 files)

AssemblySystem (8 files)

FileContent
AssemblyHandler.Core.csConstructor, fields, Initialize, 16 primary arrays (ScannedDataSources, LoadedAssembliesCompact, etc.)
AssemblyHandler.Loaders.csExtension loader discovery, ILoaderExtention/ILoaderExtention2, priority-sorted load, LoadExtensionTypes
AssemblyHandler.Scanning.csScanAllAssemblies, ScanFolder, ProcessAssembly, manifest-based type scanning
AssemblyHandler.Helpers.csType filtering, LoadAssemblySafe, logging helpers
AssemblyHandler.NuGetOperations.csNuGet package resolution via NuGetPackageManager, driver download/install
AssemblyHandler.NuGetLifecycle.csNuGet load/unload with SharedContext vs isolated ALC
AssemblyHandler.NuGetSources.csNuGet source management: nuget_sources.json, add/remove/enable/disable
AssemblyHandler.DriverTracking.csDriver scan tracking: scanned drivers, version checks, upgrade hints
AssemblyHandler.Statistics.csLoad statistics, assembly count, type count, duration tracking

PluginSystem (21 files)

FileContent
SharedContextAssemblyHandler.csShared-ALC assembly loading with type sharing across plugins
SharedContextManager.csContext lifecycle: create, dispose, type resolution across contexts
SharedAssemblyTracker.csTracks which assemblies are loaded in shared vs isolated contexts
PluginRegistry.csCentral plugin registration: discover, register, unregister
PluginManifest.csPlugin manifest model: Id, Name, Version, Dependencies, EntryPoint
PluginLifecycleManager.csPlugin lifecycle: Load, Initialize, Execute, Unload, Dispose
PluginHealthMonitor.csPlugin health checks: heartbeat, timeout detection, auto-restart
PluginIsolationManager.csAssemblyLoadContext isolation: separate ALC per plugin when needed
PluginVersionManager.csVersion compatibility checks, dependency version resolution
PluginServiceManager.csDI service registration for plugins: IPluginServiceProvider
PluginMessageBus.csIn-process pub/sub between plugins: publish, subscribe, unsubscribe
PluginProcessManager.csOut-of-process plugin hosting (IPC) for isolation
PluginInstaller.csPlugin installation from NuGet: download, extract, register
NuggetPluginLoader.csLoad plugins from installed NuGet packages
NuggetPackageDownloader.csDownloads NuGet plugin packages via NuGetPackageManager
NuggetManager.csAggregate NuGet package tracking for the PluginSystem
AssemblyScanningAssistant.csScans assemblies for plugin types (IDM_Addin, IDataSource)
AssemblyLoadingAssistant.csSafe assembly loading with error isolation per assembly
DriverDiscoveryAssistant.csDiscovers IDataSource / ConnectionDriversConfig types
InstanceCreationAssistant.csCreates instances from discovered types with DI support
UnloadAnalysis.csAnalyzes assembly dependencies before unload to prevent dangling refs
IScanningService.csScanning service contract: ScanFolder, ScanAssembly, ScanPackage

NuggetManager

public class NuggetManager
{
    // Aggregate NuGet package tracking for the PluginSystem
    public NuggetManager(IDMLogger logger, string packagesDirectory);
    public List<string> InstalledPackageIds { get; }
    public Task<bool> InstallAsync(string packageId, string version = null);
    public Task<bool> UninstallAsync(string packageId);
    public Task<bool> UpdateAsync(string packageId, string version);
    public Task<List<string>> GetOutdatedPackagesAsync();
}