Class BowirePluginLoadContext

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

Per-plugin AssemblyLoadContext that isolates plugin-private dependencies from the host and from other plugins. Plugins can carry their own versions of third-party libraries without clashing with another plugin's copy; shared contract assemblies — Kuestenlogik.Bowire*, the BCL, and the ASP.NET framework — are delegated to the default ALC so IBowireProtocol and friends keep a single identity across every context.

public sealed class BowirePluginLoadContext : AssemblyLoadContext
Inheritance
BowirePluginLoadContext
Inherited Members

Remarks

Resolution rules inside the plugin's own Load hook:

  1. Assembly name matches a shared prefix → return null, which tells the runtime to fall back to the default ALC. That's how the plugin gets the host's copy of IBowireProtocol instead of a plugin-local type that wouldn't be assignable.
  2. Otherwise, look for <AssemblyName>.dll in the plugin's directory and load it through this context.
  3. Nothing found → null, runtime raises FileNotFoundException at the call site (same contract as an unresolved reference in any ALC).

Plugins downloaded via bowire plugin install land in <pluginDir>/<packageId>/ as a flat folder of DLLs (no .deps.json), so we look for deps by filename in that folder rather than going through AssemblyDependencyResolver.

IsCollectible is true so embedded hosts can unload / hot-reload a plugin in-process via BowirePluginHost. Unload only actually reclaims memory once every reference held by the host drops — hold plugin types through WeakReference or scope them to a DI scope that disposes with the plugin.

Constructors

BowirePluginLoadContext(string, IEnumerable<string>?)

Build a context for the plugin whose DLLs live under pluginDir.

public BowirePluginLoadContext(string pluginDir, IEnumerable<string>? additionalSharedPrefixes = null)

Parameters

pluginDir string

Absolute path to the plugin's folder.

additionalSharedPrefixes IEnumerable<string>

Extra assembly-name prefixes that should also delegate to the default ALC. Embedded hosts use this to mark their own SDK assemblies as shared.

Properties

DefaultSharedPrefixes

Assembly-name prefixes that always resolve from the default ALC so every plugin shares the host's copy of the matching DLL. Covers the Bowire contract assembly, BCL types, ASP.NET, and the .NET Standard facade.

public static IReadOnlyList<string> DefaultSharedPrefixes { get; }

Property Value

IReadOnlyList<string>

PluginDirectory

Absolute directory the context resolves plugin-private deps from.

public string PluginDirectory { get; }

Property Value

string

Methods

IsShared(string?)

True when assemblyName should resolve from the default ALC rather than the plugin directory. Exposed so callers (and tests) can reason about the sharing decision without loading an assembly.

public bool IsShared(string? assemblyName)

Parameters

assemblyName string

Returns

bool

Load(AssemblyName)

protected override Assembly? Load(AssemblyName assemblyName)

Parameters

assemblyName AssemblyName

Returns

Assembly

LoadUnmanagedDll(string)

protected override nint LoadUnmanagedDll(string unmanagedDllName)

Parameters

unmanagedDllName string

Returns

nint