Skip to content

Instantly share code, notes, and snippets.

@NekkoDroid
Created April 30, 2022 18:44
Show Gist options
  • Save NekkoDroid/c5209096e74655c55708a26fe1fe6cc4 to your computer and use it in GitHub Desktop.
Save NekkoDroid/c5209096e74655c55708a26fe1fe6cc4 to your computer and use it in GitHub Desktop.
C# plugin-system (single custom ALC with shared assemblies)
public class PluginLoadContext : AssemblyLoadContext
{
public PluginLoadContext(string? name, bool isCollectible = false) : base(name, isCollectible)
{
}
public void AddDependencyResolver(string componentAssemblyPath)
{
var resolver = new AssemblyDependencyResolver(componentAssemblyPath);
Resolving += (_, assemblyName) =>
{
var assemblyPath = resolver.ResolveAssemblyToPath(assemblyName);
return assemblyPath is null ? null : LoadFromAssemblyPath(assemblyPath);
};
ResolvingUnmanagedDll += (_, unmanagedDllName) =>
{
var assemblyPath = resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
return assemblyPath is null ? IntPtr.Zero : LoadUnmanagedDllFromPath(assemblyPath);
};
}
}
var alc = new PluginLoadContext("Plugins", true); // make the custom ALC unloadable
var plugins = Array.Empty<string>(); // List of plugins to load
foreach (var plugin in plugins)
if (File.Exists(Path.ChangeExtension(plugin, ".deps.json")))
alc.AddDependencyResolver(plugin); // Used to resolve the dependencies of assemblies
var assemblies = plugins.Select(plugin =>
{
using var stream = File.OpenRead(plugin);
return alc.LoadFromStream(stream); // this is to prevent locking the assembly file
}).ToArray();
alc.Unload(); // Unloads everything as soon as all references to the assmeblies are released
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment