Class BowirePluginHost

Namespace
Kuestenlogik.Bowire.PluginLoading
Assembly
Kuestenlogik.Bowire.dll

Lifecycle manager for Bowire plugin AssemblyLoadContexts. Tracks one BowirePluginLoadContext per plugin directory (keyed by the directory's leaf name, which is the package id), and supports Unload(string) + Reload(string) so embedded hosts can swap a plugin in-process after bowire plugin update has rewritten its files.

public sealed class BowirePluginHost
Inheritance
BowirePluginHost
Inherited Members

Remarks

Unload only releases memory once the host drops every reference to plugin types. If you cache plugin instances directly the ALC lingers indefinitely. Two mitigations:

  • Resolve plugin services from a DI scope that you dispose alongside the plugin — scope-disposal drops every cached transient/scoped instance.
  • Hold plugin instances through WeakReference where you can, so the GC can collect them once usage ends.

The host itself keeps only a WeakReference to every ALC after an unload call, so it never prevents collection. Whether the unload actually completed is observable via IsUnloaded(string).

Constructors

BowirePluginHost(IEnumerable<string>?)

Build a host. Optional additional shared prefixes propagate to every plugin context.

public BowirePluginHost(IEnumerable<string>? additionalSharedPrefixes = null)

Parameters

additionalSharedPrefixes IEnumerable<string>

Properties

LoadedPlugins

Currently loaded plugin directories, keyed by package id (dir-leaf name).

public IReadOnlyDictionary<string, BowirePluginLoadContext> LoadedPlugins { get; }

Property Value

IReadOnlyDictionary<string, BowirePluginLoadContext>

Methods

IsUnloaded(string)

true when packageId was previously loaded, an unload was issued, and the GC has actually finalised the context. Useful in tests to prove the host isn't leaking references; in production the answer is usually "not yet" because the host still holds types through DI.

public bool IsUnloaded(string packageId)

Parameters

packageId string

Returns

bool

Load(string)

Load every DLL in pluginDir into a fresh BowirePluginLoadContext. If this plugin was loaded before, the previous context is unloaded first — use Reload(string) for the intended sequence so callers can distinguish a fresh install from a hot-replace.

public BowirePluginLoadContext Load(string pluginDir)

Parameters

pluginDir string

Returns

BowirePluginLoadContext

Reload(string)

Hot-replace a plugin: unload the old context and load the updated one from pluginDir. Combines Unload(string) + Load(string) with a single operation-level name for callers who want the ordering to be unambiguous.

public BowirePluginLoadContext Reload(string pluginDir)

Parameters

pluginDir string

Returns

BowirePluginLoadContext

Unload(string)

Unload the plugin with the given packageId. The underlying context is marked collectible and begins its teardown once every type reference the host holds drops. Returns false when no matching plugin is loaded.

public bool Unload(string packageId)

Parameters

packageId string

Returns

bool