embed plugin loader directly into the launcher
This commit is contained in:
135
PluginLoader/Compiler/RoslynReferences.cs
Normal file
135
PluginLoader/Compiler/RoslynReferences.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using HarmonyLib;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace PluginLoader.Compiler;
|
||||
|
||||
public static class RoslynReferences
|
||||
{
|
||||
private static readonly Dictionary<string, MetadataReference> allReferences = new();
|
||||
private static readonly HashSet<string> referenceBlacklist = new(new[] { "System.ValueTuple" });
|
||||
|
||||
public static void GenerateAssemblyList()
|
||||
{
|
||||
if (allReferences.Count > 0)
|
||||
return;
|
||||
|
||||
var harmonyInfo = typeof(Harmony).Assembly.GetName();
|
||||
|
||||
var loadedAssemblies = new Stack<Assembly>(AppDomain.CurrentDomain.GetAssemblies().Where(IsValidReference));
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine();
|
||||
var line = "===================================";
|
||||
sb.AppendLine(line);
|
||||
sb.AppendLine("Assembly References");
|
||||
sb.AppendLine(line);
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var a in loadedAssemblies)
|
||||
{
|
||||
// Prevent other Harmony versions from being loaded
|
||||
var name = a.GetName();
|
||||
if (name.Name == harmonyInfo.Name && name.Version != harmonyInfo.Version)
|
||||
{
|
||||
LogFile.WriteLine(
|
||||
$"WARNING: Multiple Harmony assemblies are loaded. Plugin Loader is using {harmonyInfo} but found {name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
AddAssemblyReference(a);
|
||||
sb.AppendLine(a.FullName);
|
||||
}
|
||||
|
||||
sb.AppendLine(line);
|
||||
while (loadedAssemblies.Count > 0)
|
||||
{
|
||||
var a = loadedAssemblies.Pop();
|
||||
|
||||
foreach (var name in a.GetReferencedAssemblies())
|
||||
{
|
||||
// Prevent other Harmony versions from being loaded
|
||||
if (name.Name == harmonyInfo.Name && name.Version != harmonyInfo.Version)
|
||||
{
|
||||
LogFile.WriteLine(
|
||||
$"WARNING: Multiple Harmony assemblies are loaded. Plugin Loader is using {harmonyInfo} but found {name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ContainsReference(name) && TryLoadAssembly(name, out var aRef) && IsValidReference(aRef))
|
||||
{
|
||||
AddAssemblyReference(aRef);
|
||||
sb.AppendLine(name.FullName);
|
||||
loadedAssemblies.Push(aRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sb.Append("Error: ").Append(e).AppendLine();
|
||||
}
|
||||
|
||||
LogFile.WriteLine(sb.ToString(), false);
|
||||
}
|
||||
|
||||
private static bool ContainsReference(AssemblyName name)
|
||||
{
|
||||
return allReferences.ContainsKey(name.Name);
|
||||
}
|
||||
|
||||
private static bool TryLoadAssembly(AssemblyName name, out Assembly aRef)
|
||||
{
|
||||
try
|
||||
{
|
||||
aRef = Assembly.Load(name);
|
||||
return true;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
aRef = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddAssemblyReference(Assembly a)
|
||||
{
|
||||
var name = a.GetName().Name;
|
||||
if (!allReferences.ContainsKey(name))
|
||||
allReferences.Add(name, MetadataReference.CreateFromFile(a.Location));
|
||||
}
|
||||
|
||||
public static IEnumerable<MetadataReference> EnumerateAllReferences()
|
||||
{
|
||||
return allReferences.Values;
|
||||
}
|
||||
|
||||
private static bool IsValidReference(Assembly a)
|
||||
{
|
||||
return !a.IsDynamic && !string.IsNullOrWhiteSpace(a.Location) && !referenceBlacklist.Contains(a.GetName().Name);
|
||||
}
|
||||
|
||||
public static void LoadReference(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
var aName = new AssemblyName(name);
|
||||
if (!allReferences.ContainsKey(aName.Name))
|
||||
{
|
||||
var a = Assembly.Load(aName);
|
||||
LogFile.WriteLine("Reference added at runtime: " + a.FullName);
|
||||
MetadataReference aRef = MetadataReference.CreateFromFile(a.Location);
|
||||
allReferences[a.GetName().Name] = aRef;
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
LogFile.WriteLine("WARNING: Unable to find the assembly '" + name + "'!");
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user