From 8ec638df88cad939fe8d05677af2250e83795be0 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Wed, 29 Jul 2026 15:59:46 -0500 Subject: [PATCH] feat(core): improve error handling for not found plugin assemblies Add PluginNotFoundException to provide a clear and actionable error when a configured plugin assembly cannot be found. Validate the plugin assembly path before creating AssemblyDependencyResolver and include the expected plugin path in the exception message. --- .../Exceptions/PluginNotFoundException.cs | 19 +++++++++++++++++++ src/Core/PluginLoadContext.cs | 14 ++++++++++++++ src/Core/PluginLoader.cs | 3 +++ tests/CPlugin.Net/Core/PluginLoaderTests.cs | 17 +++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/Core/Exceptions/PluginNotFoundException.cs diff --git a/src/Core/Exceptions/PluginNotFoundException.cs b/src/Core/Exceptions/PluginNotFoundException.cs new file mode 100644 index 0000000..69a407f --- /dev/null +++ b/src/Core/Exceptions/PluginNotFoundException.cs @@ -0,0 +1,19 @@ +using System; + +namespace CPlugin.Net; + +/// +/// The exception that is thrown when a plugin assembly cannot be found. +/// +public class PluginNotFoundException : Exception +{ + /// + /// Initializes a new instance of the class. + /// + /// + /// The message that describes the error. + /// + public PluginNotFoundException(string message) : base(message) + { + } +} diff --git a/src/Core/PluginLoadContext.cs b/src/Core/PluginLoadContext.cs index 77cbf5a..025d279 100644 --- a/src/Core/PluginLoadContext.cs +++ b/src/Core/PluginLoadContext.cs @@ -10,6 +10,20 @@ internal class PluginLoadContext : AssemblyLoadContext public PluginLoadContext(string pluginPath) { + if (!File.Exists(pluginPath)) + { + var message = + $""" + The plugin '{Path.GetFileName(pluginPath)}' was not found at: + + {pluginPath} + + Ensure the plugin project has been built and the assembly exists in the plugins directory. + """; + + throw new PluginNotFoundException(message); + } + _resolver = new AssemblyDependencyResolver(pluginPath); } diff --git a/src/Core/PluginLoader.cs b/src/Core/PluginLoader.cs index f0d6de5..973e7ab 100644 --- a/src/Core/PluginLoader.cs +++ b/src/Core/PluginLoader.cs @@ -33,6 +33,9 @@ public static class PluginLoader /// /// A plugin declares a dependency that cannot be resolved. /// + /// + /// A configured plugin assembly could not be found. + /// public static void Load(CPluginConfigurationBase configuration) { ArgumentNullException.ThrowIfNull(configuration); diff --git a/tests/CPlugin.Net/Core/PluginLoaderTests.cs b/tests/CPlugin.Net/Core/PluginLoaderTests.cs index 9198ec3..818cc2e 100644 --- a/tests/CPlugin.Net/Core/PluginLoaderTests.cs +++ b/tests/CPlugin.Net/Core/PluginLoaderTests.cs @@ -129,4 +129,21 @@ public void Load_WhenPluginDependencyIsResolved_ShouldLoadPluginsSuccessfully() string weapons = gameModes[0].ExecuteAction(); weapons.Should().Be("Pistol, AK-47"); } + + [Test] + public void Load_WhenPluginIsNotFound_ShouldThrowPluginNotFoundException() + { + // Arrange + var value = "Example.EconomyPlugin.dll"; + Environment.SetEnvironmentVariable("PLUGINS", value); + var configuration = new CPluginEnvConfiguration(); + + // Act + Action act = () => PluginLoader.Load(configuration); + + // Assert + act.Should() + .Throw() + .WithMessage("*Example.EconomyPlugin.dll*"); + } }