135 lines
4.2 KiB
C#
135 lines
4.2 KiB
C#
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 + "'!");
|
|
}
|
|
}
|
|
} |