Skip to content

release: plugin loader (0.24.0)#66

Merged
tgiachi merged 10 commits into
mainfrom
develop
Jul 6, 2026
Merged

release: plugin loader (0.24.0)#66
tgiachi merged 10 commits into
mainfrom
develop

Conversation

@tgiachi

@tgiachi tgiachi commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Promotes develop to main:

  • New SquidStd.Plugin package (PR feat(plugin): add SquidStd.Plugin loader package #65): UsePlugins loader for internal (by type/instance) and external (directory scan, default ALC) plugins, dependency-sorted across the whole set, Configure invoked before the configuration load, fail-fast PluginLoadException, standard PluginContext keys.
  • ISquidStdBootstrap.State + public BootstrapStateType (pre-start guard support).
  • Plugins sample boots through the loader; new docs article and READMEs.

Test plan

tgiachi added 10 commits July 6, 2026 10:06
Moves BootstrapStateType from SquidStd.Services.Core (internal) to
SquidStd.Core.Types.Bootstrap (public) and adds a read-only State
property so external packages can guard pre-start-only operations.
… context keys

New loader package skeleton referencing Core and Plugin.Abstractions:
PluginCollectionBuilder (internal plugins by type or instance, external
directories), PluginLoadException, standard PluginContextKeys, and
host-agnostic wording in the abstractions docs.
Topological sort across the whole plugin set with fail-fast errors for
duplicate ids, missing dependencies, and cycles (the message names the
cycle members). Plugins with no dependency relation keep registration
order.
Scans a directory for *.dll files, loads them into the default
AssemblyLoadContext (trusted plugins, shared type identity), and
instantiates every concrete ISquidStdPlugin. Assemblies without plugins
are skipped with a debug log; load and instantiation failures and a
missing directory fail fast with PluginLoadException. Tests emit plugin
assemblies at run time with Roslyn, so no binary fixtures are committed.
UsePlugins collects internal and external plugins, sorts them across the
whole set, and configures each against the bootstrap container before
startup, populating the standard PluginContext keys. Guarded to the
Created bootstrap state. The plugins sample now boots through the loader.
Package README with the UsePlugins example, loading rules, context keys
and the trusted-plugin contract; docs article and toc entry; pointer from
the abstractions README.
feat(plugin): add SquidStd.Plugin loader package
Comment on lines +53 to +60
foreach (var directory in builder.Directories)
{
var resolved = Path.IsPathRooted(directory)
? directory
: Path.Combine(bootstrap.Options.RootDirectory, directory);

plugins.AddRange(PluginAssemblyScanner.Scan(resolved));
}
{
var resolved = Path.IsPathRooted(directory)
? directory
: Path.Combine(bootstrap.Options.RootDirectory, directory);
Comment on lines +50 to +53
catch (Exception ex)
{
throw new PluginLoadException($"Failed to load plugin assembly '{dllPath}'.", ex);
}
Comment on lines +68 to +74
catch (Exception ex)
{
throw new PluginLoadException(
$"Failed to instantiate plugin type '{pluginType.FullName}' from '{dllPath}'.",
ex
);
}
Comment on lines +17 to +23
foreach (var plugin in plugins)
{
if (!byId.TryAdd(plugin.Metadata.Id, plugin))
{
throw new PluginLoadException($"Duplicate plugin id '{plugin.Metadata.Id}'.");
}
}
[Fact]
public void Scan_MissingDirectory_Throws()
{
var missing = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));

try
{
File.WriteAllBytes(Path.Combine(directory.FullName, "broken.dll"), [1, 2, 3, 4]);
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);

var path = Path.Combine(directory, fileName);
@tgiachi
tgiachi merged commit 6fcddd9 into main Jul 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants