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)
|
internal static void ConfigureAssemblyResolver(AssemblyDefinitionResolver resolver)
|
||||||
{
|
{
|
||||||
// add search paths
|
// add search paths
|
||||||
resolver.AddSearchDirectory(Constants.GamePath);
|
resolver.TryAddSearchDirectory(Constants.GamePath);
|
||||||
resolver.AddSearchDirectory(Constants.InternalFilesPath);
|
resolver.TryAddSearchDirectory(Constants.InternalFilesPath);
|
||||||
|
|
||||||
// add SMAPI explicitly
|
// add SMAPI explicitly
|
||||||
// Normally this would be handled automatically by the search paths, but for some reason there's a specific
|
// 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
|
namespace StardewModdingAPI.Framework.ModLoading
|
||||||
{
|
{
|
||||||
/// <summary>A minimal assembly definition resolver which resolves references to known assemblies.</summary>
|
/// <summary>A minimal assembly definition resolver which resolves references to known assemblies.</summary>
|
||||||
internal class AssemblyDefinitionResolver : DefaultAssemblyResolver
|
internal class AssemblyDefinitionResolver : IAssemblyResolver
|
||||||
{
|
{
|
||||||
/*********
|
/*********
|
||||||
** Fields
|
** Fields
|
||||||
*********/
|
*********/
|
||||||
|
/// <summary>The underlying assembly resolver.</summary>
|
||||||
|
private readonly DefaultAssemblyResolverWrapper Resolver = new();
|
||||||
|
|
||||||
/// <summary>The known assemblies.</summary>
|
/// <summary>The known assemblies.</summary>
|
||||||
private readonly IDictionary<string, AssemblyDefinition> Lookup = new Dictionary<string, AssemblyDefinition>();
|
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
|
** 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>
|
/// <summary>Add known assemblies to the resolver.</summary>
|
||||||
/// <param name="assemblies">The known assemblies.</param>
|
/// <param name="assemblies">The known assemblies.</param>
|
||||||
public void Add(params AssemblyDefinition[] assemblies)
|
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>
|
/// <param name="names">The assembly names for which it should be returned.</param>
|
||||||
public void AddWithExplicitNames(AssemblyDefinition assembly, params string[] names)
|
public void AddWithExplicitNames(AssemblyDefinition assembly, params string[] names)
|
||||||
{
|
{
|
||||||
this.RegisterAssembly(assembly);
|
this.Resolver.AddAssembly(assembly);
|
||||||
foreach (string name in names)
|
foreach (string name in names)
|
||||||
this.Lookup[name] = assembly;
|
this.Lookup[name] = assembly;
|
||||||
}
|
}
|
||||||
|
@ -37,18 +50,52 @@ namespace StardewModdingAPI.Framework.ModLoading
|
||||||
/// <summary>Resolve an assembly reference.</summary>
|
/// <summary>Resolve an assembly reference.</summary>
|
||||||
/// <param name="name">The assembly name.</param>
|
/// <param name="name">The assembly name.</param>
|
||||||
/// <exception cref="AssemblyResolutionException">The assembly can't be resolved.</exception>
|
/// <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>
|
/// <summary>Resolve an assembly reference.</summary>
|
||||||
/// <param name="name">The assembly name.</param>
|
/// <param name="name">The assembly name.</param>
|
||||||
/// <param name="parameters">The assembly reader parameters.</param>
|
/// <param name="parameters">The assembly reader parameters.</param>
|
||||||
/// <exception cref="AssemblyResolutionException">The assembly can't be resolved.</exception>
|
/// <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
|
? match
|
||||||
: null;
|
: 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
|
// add the assembly's directory temporarily if needed
|
||||||
// this is needed by F# mods which bundle FSharp.Core.dll, for example
|
// this is needed by F# mods which bundle FSharp.Core.dll, for example
|
||||||
string? temporarySearchDir = null;
|
string? temporarySearchDir = null;
|
||||||
if (file.DirectoryName is not null && !this.AssemblyDefinitionResolver.GetSearchDirectories().Contains(file.DirectoryName))
|
if (this.AssemblyDefinitionResolver.TryAddSearchDirectory(file.DirectoryName))
|
||||||
{
|
|
||||||
this.AssemblyDefinitionResolver.AddSearchDirectory(file.DirectoryName);
|
|
||||||
temporarySearchDir = file.DirectoryName;
|
temporarySearchDir = file.DirectoryName;
|
||||||
}
|
|
||||||
|
|
||||||
// read assembly
|
// read assembly
|
||||||
AssemblyDefinition assembly;
|
AssemblyDefinition assembly;
|
||||||
|
|
Loading…
Reference in New Issue