diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 33468717..442f2ec8 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -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
diff --git a/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs b/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs
index b3378ad1..5a850255 100644
--- a/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs
+++ b/src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs
@@ -4,18 +4,31 @@ using Mono.Cecil;
namespace StardewModdingAPI.Framework.ModLoading
{
/// A minimal assembly definition resolver which resolves references to known assemblies.
- internal class AssemblyDefinitionResolver : DefaultAssemblyResolver
+ internal class AssemblyDefinitionResolver : IAssemblyResolver
{
/*********
** Fields
*********/
+ /// The underlying assembly resolver.
+ private readonly DefaultAssemblyResolverWrapper Resolver = new();
+
/// The known assemblies.
private readonly IDictionary Lookup = new Dictionary();
+ /// The directory paths to search for assemblies.
+ private readonly HashSet SearchPaths = new();
+
/*********
** Public methods
*********/
+ /// Construct an instance.
+ public AssemblyDefinitionResolver()
+ {
+ foreach (string path in this.Resolver.GetSearchDirectories())
+ this.SearchPaths.Add(path);
+ }
+
/// Add known assemblies to the resolver.
/// The known assemblies.
public void Add(params AssemblyDefinition[] assemblies)
@@ -29,7 +42,7 @@ namespace StardewModdingAPI.Framework.ModLoading
/// The assembly names for which it should be returned.
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
/// Resolve an assembly reference.
/// The assembly name.
/// The assembly can't be resolved.
- 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);
}
/// Resolve an assembly reference.
/// The assembly name.
/// The assembly reader parameters.
/// The assembly can't be resolved.
- 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);
+ }
+
+ /// Add a directory path to search for assemblies, if it's non-null and not already added.
+ /// The path to search.
+ /// Returns whether the path was successfully added.
+ public bool TryAddSearchDirectory(string? path)
+ {
+ if (path is not null && this.SearchPaths.Add(path))
+ {
+ this.Resolver.AddSearchDirectory(path);
+ return true;
+ }
+
+ return false;
+ }
+
+ /// Remove a directory path to search for assemblies, if it's non-null.
+ /// The path to remove.
+ /// Returns whether the path was in the list and removed.
+ public bool RemoveSearchDirectory(string? path)
+ {
+ if (path is not null && this.SearchPaths.Remove(path))
+ {
+ this.Resolver.RemoveSearchDirectory(path);
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ public void Dispose()
+ {
+ this.Resolver.Dispose();
}
@@ -63,5 +110,16 @@ namespace StardewModdingAPI.Framework.ModLoading
? match
: null;
}
+
+ /// An internal wrapper around to allow access to its protected methods.
+ private class DefaultAssemblyResolverWrapper : DefaultAssemblyResolver
+ {
+ /// Add an assembly to the resolver.
+ /// The assembly to add.
+ public void AddAssembly(AssemblyDefinition assembly)
+ {
+ this.RegisterAssembly(assembly);
+ }
+ }
}
}
diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
index bd29a159..01037870 100644
--- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
+++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
@@ -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;