acdream/src/AcDream.Core/Plugins/PluginAssemblyLoadContext.cs
Erik f6a57cbc6c refactor(core): harden PluginLoader per code review
Addresses code quality review of a7f0732:
- LoadedPlugin now holds the AssemblyLoadContext explicitly so Task 10
  can call Unload() for hot reload (Critical)
- LoadedPlugin.Error is Exception? to match PluginDiscoveryResult and
  preserve stack traces; synthetic failures build FileNotFoundException
  and InvalidOperationException (Important)
- PluginLoader falls back to ReflectionTypeLoadException.Types if
  GetTypes() can't fully resolve (Important)
- Hardcoded abstractions assembly name is now a const (Minor)
2026-04-10 09:57:45 +02:00

32 lines
1.2 KiB
C#

using System.Reflection;
using System.Runtime.Loader;
namespace AcDream.Core.Plugins;
/// <summary>
/// Collectible ALC for a single plugin. Resolves assemblies from the plugin's
/// own directory EXCEPT for AcDream.Plugin.Abstractions, which must come from
/// the default (host) context so type identity for IAcDreamPlugin is preserved.
/// </summary>
internal sealed class PluginAssemblyLoadContext : AssemblyLoadContext
{
private const string AbstractionsAssemblyName = "AcDream.Plugin.Abstractions";
private readonly AssemblyDependencyResolver _resolver;
public PluginAssemblyLoadContext(string pluginDirectory, string pluginEntryPath)
: base(name: pluginDirectory, isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(pluginEntryPath);
}
protected override Assembly? Load(AssemblyName assemblyName)
{
// Share the abstractions assembly with the host — do NOT reload it in the plugin ALC
if (assemblyName.Name == AbstractionsAssemblyName)
return null;
var path = _resolver.ResolveAssemblyToPath(assemblyName);
return path is null ? null : LoadFromAssemblyPath(path);
}
}