Forge
csharp3407750f
1using System.Reflection;
2using System.Runtime.Loader;
3
4namespace AgentForge.Plugins;
5
6/// <summary>Collectible ALC for one plugin assembly (FORGE-ADR-0023 HR3).</summary>
7internal sealed class ForgePluginLoadContext(string pluginId, string pluginAssemblyPath) : AssemblyLoadContext($"forge-plugin-{pluginId}", isCollectible: true)
8{
9 private readonly AssemblyDependencyResolver _resolver = new(pluginAssemblyPath);
10
11 internal string PluginId { get; } = pluginId;
12
13 internal string AssemblyPath { get; } = pluginAssemblyPath;
14
15 protected override Assembly? Load(AssemblyName assemblyName)
16 {
17 var name = assemblyName.Name;
18 if (name is not null)
19 {
20 var inDefault = Default.Assemblies.FirstOrDefault(a =>
21 string.Equals(a.GetName().Name, name, StringComparison.Ordinal));
22 if (inDefault is not null)
23 return inDefault;
24
25 if (IsSharedWithHost(name))
26 {
27 var hostPath = Path.Combine(AppContext.BaseDirectory, $"{name}.dll");
28 if (File.Exists(hostPath))
29 return Default.LoadFromAssemblyPath(hostPath);
30
31 return Default.LoadFromAssemblyName(assemblyName);
32 }
33 }
34
35 var path = _resolver.ResolveAssemblyToPath(assemblyName);
36 if (path is null && name is not null)
37 {
38 var sibling = Path.Combine(Path.GetDirectoryName(AssemblyPath)!, $"{name}.dll");
39 if (File.Exists(sibling))
40 path = sibling;
41 }
42
43 return path is not null ? LoadFromAssemblyPath(path) : null;
44 }
45
46 protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
47 {
48 var path = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
49 return path is not null ? LoadUnmanagedDllFromPath(path) : IntPtr.Zero;
50 }
51
52 private static bool IsSharedWithHost(string assemblyName) =>
53 assemblyName.StartsWith("AgentForge.Abstractions", StringComparison.Ordinal)
54 || assemblyName.StartsWith("AgentForge.Plugin.Sdk", StringComparison.Ordinal)
55 || assemblyName.StartsWith("AgentForge.Mcp.Core", StringComparison.Ordinal)
56 || assemblyName.StartsWith("AgentForge.Plugin.ViewShell", StringComparison.Ordinal)
57 || assemblyName.StartsWith("AgentForge.Plugin.View", StringComparison.Ordinal)
58 || assemblyName.StartsWith("AgentForge.Plugin.RepositoryImport.GitHub.Core", StringComparison.Ordinal)
59 || assemblyName.StartsWith("Microsoft.", StringComparison.Ordinal)
60 || assemblyName.StartsWith("System.", StringComparison.Ordinal)
61 || assemblyName.StartsWith("netstandard", StringComparison.Ordinal);
62}
63
View only · write via MCP/CIDE