Skip to content

WarpClock: support true plug-in hot-reload via collectible AssemblyLoadContext unload #13

Description

@KlausLoeffelmann

Summary

WarpClock.App loads theme plug-ins in-process, each into its own collectible AssemblyLoadContext (ThemePluginLoader.PluginLoadContext, isCollectible: true), deferring shared contracts (WarpClock.Abstractions, WarpToolkit.WinForms.DirectX, runtime) to the default context so plug-in IClockTheme types share identity with the host. This part of the design is already correct.

However, the collectible contexts are never unloaded, so true hot-reload does not work today.

Current behavior

  • ThemePluginLoader accumulates every PluginLoadContext in _contexts and never disposes/unloads them.
  • _loadedPaths guards against re-loading a path that was already loaded. On a FileSystemWatcher-triggered change, a modified DLL at an already-seen path is skipped — its new content is ignored until the app restarts.
  • Net effect: "load-once" semantics. Dropping a new DLL works; changing an existing one does not hot-reload.

Proposed work (future)

Implement real unload-and-reload semantics using the collectible ALCs we already create:

  1. Track the PluginLoadContext (and discovered themes) per source path.
  2. On a watcher change for an already-loaded path:
    • Remove/dispose any live theme instances originating from that assembly.
    • Call AssemblyLoadContext.Unload() on the old context and drop it from _contexts.
    • Remove the path from _loadedPaths.
    • Reload the assembly into a fresh collectible context.
  3. Handle the asynchronous nature of ALC unload (GC-driven) — references must be released before the context can collect; surface/await accordingly.
  4. Keep everything serialized through the existing _loadGate so the worker-thread initial load and watcher-triggered reloads can never race.

Notes

  • This is intentionally deferred; the current demo ships with "load-once" behavior on purpose.
  • Relevant files:
    • src/WinForms/NET11/WarpClock/WarpClock.App/ThemePluginLoader.cs
    • src/WinForms/NET11/WarpClock/WarpClock.App/FormMain.cs (watcher + _loadGate + LoadPluginsAsync)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic-assemblyloadcontextAssemblyLoadContext: dynamic loading, isolation, collectible unloadtopic-winforms-appbootstrappingWinForms application bootstrapping and startup wiringtopic-winforms-asyncWinForms async/await, threading and UI marshaling

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions