-
-
Notifications
You must be signed in to change notification settings - Fork 142
Open
Labels
Description
Problem
I want to load a self-contained directory of assemblies, and have all the references line up. This is extremely common for Unity games.
internal class Program
{
static void Main(string[] args)
{
AssemblyResolver resolver = new AssemblyResolver(args[0]);
RuntimeContext context = new(new DotNetRuntimeInfo(DotNetRuntimeInfo.NetFramework, new Version(4, 0, 0, 0)), resolver);
List<AssemblyDefinition> assemblies = new();
foreach (string path in Directory.EnumerateFiles(args[0], "*.dll"))
{
AssemblyDefinition assembly = AssemblyDefinition.FromFile(path, new ModuleReaderParameters(context));
assemblies.Add(assembly);
}
//Using the assembly list
}
private sealed class AssemblyResolver : AssemblyResolverBase
{
public AssemblyResolver(string directory) : base(new ModuleReaderParameters(directory))
{
SearchDirectories.Add(directory);
}
protected override string? ProbeRuntimeDirectories(AssemblyDescriptor assembly)
{
return null;
}
}
}I know mscorlib gets loaded twice because I have TypeDefinition objects that are signature equal (SignatureComparer), but not reference equal.
Ideal Solution
I propose we add AssemblyDefinition.FromFiles and ModuleDefinition.FromFiles.
Workaround
This is how I'm currently working around the issue.
private static List<ModuleDefinition> LoadModules(string directory)
{
AssemblyResolver resolver = new AssemblyResolver(directory);
return Directory.EnumerateFiles(directory, "*.dll")
.Order()
.Select(resolver.LoadModuleFromFile)
.ToList();
}
private sealed class AssemblyResolver : AssemblyResolverBase
{
private readonly ConcurrentDictionary<string, AssemblyDefinition> fileCache = new();
public AssemblyResolver(string directory) : base(new ModuleReaderParameters(directory))
{
SearchDirectories.Add(directory);
ReaderParameters.RuntimeContext = new RuntimeContext(new DotNetRuntimeInfo(DotNetRuntimeInfo.NetFramework, new Version(4, 0, 0, 0)), this);
}
protected override string? ProbeRuntimeDirectories(AssemblyDescriptor assembly)
{
throw new NotSupportedException();
}
public ModuleDefinition LoadModuleFromFile(string path)
{
return LoadAssemblyFromFile(path).ManifestModule!;
}
protected override AssemblyDefinition LoadAssemblyFromFile(string path)
{
if (fileCache.TryGetValue(path, out AssemblyDefinition? assembly))
{
return assembly;
}
else
{
assembly = base.LoadAssemblyFromFile(path);
fileCache.TryAdd(path, assembly);
return assembly;
}
}
}