refactor assembly resolver to avoid repeatedly copying search directory list
This commit is contained in:
parent
0c0f7898f4
commit
1b3a1a48d0
|
@ -244,8 +244,8 @@ namespace StardewModdingAPI
|
|||
internal static void ConfigureAssemblyResolver(AssemblyDefinitionResolver resolver)
|
||||
{
|
||||
// add search paths
|
||||
resolver.AddSearchDirectory(Constants.GamePath);
|
||||
resolver.AddSearchDirectory(Constants.InternalFilesPath);
|
||||
resolver.TryAddSearchDirectory(Constants.GamePath);
|
||||
resolver.TryAddSearchDirectory(Constants.InternalFilesPath);
|
||||
|
||||
// add SMAPI explicitly
|
||||
// Normally this would be handled automatically by the search paths, but for some reason there's a specific
|
||||
|
|
|
@ -4,18 +4,31 @@ using Mono.Cecil;
|
|||
namespace StardewModdingAPI.Framework.ModLoading
|
||||
{
|
||||
/// <summary>A minimal assembly definition resolver which resolves references to known assemblies.</summary>
|
||||
internal class AssemblyDefinitionResolver : DefaultAssemblyResolver
|
||||
internal class AssemblyDefinitionResolver : IAssemblyResolver
|
||||
{
|
||||
/*********
|
||||
** Fields
|
||||
*********/
|
||||
/// <summary>The underlying assembly resolver.</summary>
|
||||
private readonly DefaultAssemblyResolverWrapper Resolver = new();
|
||||
|
||||
/// <summary>The known assemblies.</summary>
|
||||
private readonly IDictionary<string, AssemblyDefinition> Lookup = new Dictionary<string, AssemblyDefinition>();
|
||||
|
||||
/// <summary>The directory paths to search for assemblies.</summary>
|
||||
private readonly HashSet<string> SearchPaths = new();
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Construct an instance.</summary>
|
||||
public AssemblyDefinitionResolver()
|
||||
{
|
||||
foreach (string path in this.Resolver.GetSearchDirectories())
|
||||
this.SearchPaths.Add(path);
|
||||
}
|
||||
|
||||
/// <summary>Add known assemblies to the resolver.</summary>
|
||||
/// <param name="assemblies">The known assemblies.</param>
|
||||
public void Add(params AssemblyDefinition[] assemblies)
|
||||
|
@ -29,7 +42,7 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
/// <param name="names">The assembly names for which it should be returned.</param>
|
||||
public void AddWithExplicitNames(AssemblyDefinition assembly, params string[] names)
|
||||
{
|
||||
this.RegisterAssembly(assembly);
|
||||
this.Resolver.AddAssembly(assembly);
|
||||
foreach (string name in names)
|
||||
this.Lookup[name] = assembly;
|
||||
}
|
||||
|
@ -37,18 +50,52 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
/// <summary>Resolve an assembly reference.</summary>
|
||||
/// <param name="name">The assembly name.</param>
|
||||
/// <exception cref="AssemblyResolutionException">The assembly can't be resolved.</exception>
|
||||
public override AssemblyDefinition Resolve(AssemblyNameReference name)
|
||||
public AssemblyDefinition Resolve(AssemblyNameReference name)
|
||||
{
|
||||
return this.ResolveName(name.Name) ?? base.Resolve(name);
|
||||
return this.ResolveName(name.Name) ?? this.Resolver.Resolve(name);
|
||||
}
|
||||
|
||||
/// <summary>Resolve an assembly reference.</summary>
|
||||
/// <param name="name">The assembly name.</param>
|
||||
/// <param name="parameters">The assembly reader parameters.</param>
|
||||
/// <exception cref="AssemblyResolutionException">The assembly can't be resolved.</exception>
|
||||
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
|
||||
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters)
|
||||
{
|
||||
return this.ResolveName(name.Name) ?? base.Resolve(name, parameters);
|
||||
return this.ResolveName(name.Name) ?? this.Resolver.Resolve(name, parameters);
|
||||
}
|
||||
|
||||
/// <summary>Add a directory path to search for assemblies, if it's non-null and not already added.</summary>
|
||||
/// <param name="path">The path to search.</param>
|
||||
/// <returns>Returns whether the path was successfully added.</returns>
|
||||
public bool TryAddSearchDirectory(string? path)
|
||||
{
|
||||
if (path is not null && this.SearchPaths.Add(path))
|
||||
{
|
||||
this.Resolver.AddSearchDirectory(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Remove a directory path to search for assemblies, if it's non-null.</summary>
|
||||
/// <param name="path">The path to remove.</param>
|
||||
/// <returns>Returns whether the path was in the list and removed.</returns>
|
||||
public bool RemoveSearchDirectory(string? path)
|
||||
{
|
||||
if (path is not null && this.SearchPaths.Remove(path))
|
||||
{
|
||||
this.Resolver.RemoveSearchDirectory(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
this.Resolver.Dispose();
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,5 +110,16 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
? match
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>An internal wrapper around <see cref="DefaultAssemblyResolver"/> to allow access to its protected methods.</summary>
|
||||
private class DefaultAssemblyResolverWrapper : DefaultAssemblyResolver
|
||||
{
|
||||
/// <summary>Add an assembly to the resolver.</summary>
|
||||
/// <param name="assembly">The assembly to add.</param>
|
||||
public void AddAssembly(AssemblyDefinition assembly)
|
||||
{
|
||||
this.RegisterAssembly(assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -267,11 +267,8 @@ namespace StardewModdingAPI.Framework.ModLoading
|
|||
// add the assembly's directory temporarily if needed
|
||||
// this is needed by F# mods which bundle FSharp.Core.dll, for example
|
||||
string? temporarySearchDir = null;
|
||||
if (file.DirectoryName is not null && !this.AssemblyDefinitionResolver.GetSearchDirectories().Contains(file.DirectoryName))
|
||||
{
|
||||
this.AssemblyDefinitionResolver.AddSearchDirectory(file.DirectoryName);
|
||||
if (this.AssemblyDefinitionResolver.TryAddSearchDirectory(file.DirectoryName))
|
||||
temporarySearchDir = file.DirectoryName;
|
||||
}
|
||||
|
||||
// read assembly
|
||||
AssemblyDefinition assembly;
|
||||
|
|
Loading…
Reference in New Issue