Allow plugins to find non-harmony types in other plugins
All checks were successful
Build / Compute Version (push) Successful in 4s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 1m50s
Build / Build Nuget package (NuGet) (push) Successful in 1m50s
Build / Build Nuget package (CringePlugins) (push) Successful in 2m17s
Build / Build Nuget package (SharedCringe) (push) Successful in 2m38s
Build / Build Launcher (push) Successful in 3m16s
All checks were successful
Build / Compute Version (push) Successful in 4s
Build / Build Nuget package (CringeBootstrap.Abstractions) (push) Successful in 1m50s
Build / Build Nuget package (NuGet) (push) Successful in 1m50s
Build / Build Nuget package (CringePlugins) (push) Successful in 2m17s
Build / Build Nuget package (SharedCringe) (push) Successful in 2m38s
Build / Build Launcher (push) Successful in 3m16s
This commit is contained in:
@@ -78,6 +78,19 @@ public static class IntrospectionPatches
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix, HarmonyPatch(typeof(AccessTools), nameof(AccessTools.TypeByName))]
|
||||||
|
private static bool TypeByNameHarmonyPrefix(ref Type __result, string name)
|
||||||
|
{
|
||||||
|
if (!PluginAssemblyLoadContext.TypeToAssembly.TryGetValue(name, out var assembly))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var module = assembly.GetMainModule();
|
||||||
|
|
||||||
|
__result = module.GetType(name, true, false)!;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyPrefix, HarmonyPatch(typeof(AccessTools), nameof(AccessTools.AllAssemblies))]
|
[HarmonyPrefix, HarmonyPatch(typeof(AccessTools), nameof(AccessTools.AllAssemblies))]
|
||||||
private static bool AllAssembliesHarmonyPrefix(ref IEnumerable<Assembly> __result)
|
private static bool AllAssembliesHarmonyPrefix(ref IEnumerable<Assembly> __result)
|
||||||
{
|
{
|
||||||
|
@@ -1,23 +1,51 @@
|
|||||||
using System.Reflection;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
using CringeBootstrap.Abstractions;
|
using CringeBootstrap.Abstractions;
|
||||||
|
using CringePlugins.Utils;
|
||||||
using SharedCringe.Loader;
|
using SharedCringe.Loader;
|
||||||
|
|
||||||
namespace CringePlugins.Loader;
|
namespace CringePlugins.Loader;
|
||||||
|
|
||||||
internal class PluginAssemblyLoadContext : DerivedAssemblyLoadContext
|
internal class PluginAssemblyLoadContext : DerivedAssemblyLoadContext
|
||||||
{
|
{
|
||||||
|
//todo: refactor?
|
||||||
|
public static readonly ConcurrentDictionary<string, Assembly> TypeToAssembly = [];
|
||||||
|
|
||||||
private readonly string _entrypointPath;
|
private readonly string _entrypointPath;
|
||||||
private readonly AssemblyDependencyResolver _dependencyResolver;
|
private readonly AssemblyDependencyResolver _dependencyResolver;
|
||||||
|
private readonly HashSet<string> _loadedTypes = [];
|
||||||
private Assembly? _assembly;
|
private Assembly? _assembly;
|
||||||
|
|
||||||
internal PluginAssemblyLoadContext(ICoreLoadContext parentContext, string entrypointPath) : base(parentContext, $"Plugin Context {Path.GetFileNameWithoutExtension(entrypointPath)}")
|
internal PluginAssemblyLoadContext(ICoreLoadContext parentContext, string entrypointPath) : base(parentContext, $"Plugin Context {Path.GetFileNameWithoutExtension(entrypointPath)}")
|
||||||
{
|
{
|
||||||
_entrypointPath = entrypointPath;
|
_entrypointPath = entrypointPath;
|
||||||
_dependencyResolver = new(entrypointPath);
|
_dependencyResolver = new(entrypointPath);
|
||||||
|
|
||||||
|
Unloading += OnUnload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Assembly LoadEntrypoint() => _assembly ??= LoadFromAssemblyPath(_entrypointPath);
|
public Assembly LoadEntrypoint()
|
||||||
|
{
|
||||||
|
if (_assembly is not null)
|
||||||
|
return _assembly;
|
||||||
|
|
||||||
|
_assembly = LoadFromAssemblyPath(_entrypointPath);
|
||||||
|
|
||||||
|
var module = _assembly.GetMainModule();
|
||||||
|
|
||||||
|
foreach (var type in module.GetTypes())
|
||||||
|
{
|
||||||
|
var name = type.FullName?.Replace('/', '+');
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(name) || !_loadedTypes.Add(name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TypeToAssembly[name] = _assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _assembly;
|
||||||
|
}
|
||||||
|
|
||||||
protected override Assembly? Load(AssemblyName assemblyName)
|
protected override Assembly? Load(AssemblyName assemblyName)
|
||||||
{
|
{
|
||||||
@@ -34,4 +62,16 @@ internal class PluginAssemblyLoadContext : DerivedAssemblyLoadContext
|
|||||||
|
|
||||||
return base.LoadUnmanagedDll(unmanagedDllName);
|
return base.LoadUnmanagedDll(unmanagedDllName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void OnUnload(AssemblyLoadContext context)
|
||||||
|
{
|
||||||
|
if (context is not PluginAssemblyLoadContext pluginContext)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var typeStr in pluginContext._loadedTypes)
|
||||||
|
{
|
||||||
|
TypeToAssembly.Remove(typeStr);
|
||||||
|
}
|
||||||
|
pluginContext._loadedTypes.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user