Skip to content

Resolved references should align when loading a self contained folder #580

@ds5678

Description

@ds5678

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;
		}
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugdotnetIssues related to AsmResolver.DotNet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions