From 7725cc3b0524c20a70cbedfe0f1b6add85d5de57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Th=C3=A9ate?= <97221392+antoineatstariongroup@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:01:10 +0100 Subject: [PATCH] Fix bug on DLL resolve for plugins (#380) * Fix bug on DLL resolve for plugins * Increase waiting time --- .github/workflows/CodeQuality.yml | 2 +- .../AuthenticationPluginInjector.cs | 38 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CodeQuality.yml b/.github/workflows/CodeQuality.yml index e548219f..de987574 100644 --- a/.github/workflows/CodeQuality.yml +++ b/.github/workflows/CodeQuality.yml @@ -79,7 +79,7 @@ jobs: run: dotnet-coverage collect --output CoverageResults/integration.test.report.coverage.xml --output-format cobertura --session-id integrationtestsession "dotnet run --project CometServer/CometServer.csproj -c Debug" & - name: Wait for API to start - run: sleep 45 # Adjust as necessary to ensure the API is up + run: sleep 60 # Adjust as necessary to ensure the API is up - name: Checkout Integration Test Suite uses: actions/checkout@v4 diff --git a/CometServer/Authentication/AuthenticationPluginInjector.cs b/CometServer/Authentication/AuthenticationPluginInjector.cs index b0832ee4..146d9c84 100644 --- a/CometServer/Authentication/AuthenticationPluginInjector.cs +++ b/CometServer/Authentication/AuthenticationPluginInjector.cs @@ -41,8 +41,13 @@ namespace CometServer.Authentication /// /// The injector loads up authenticator plugins. /// - public class AuthenticationPluginInjector : IAuthenticationPluginInjector + public class AuthenticationPluginInjector : IAuthenticationPluginInjector, IDisposable { + /// + /// A collection of that has been discovered + /// + private List discoveredAssemblies = new List(); + /// /// The name of the folder where all authentication modules reside. /// @@ -59,6 +64,7 @@ public class AuthenticationPluginInjector : IAuthenticationPluginInjector public AuthenticationPluginInjector(ILogger logger) { this.logger = logger; + AppDomain.CurrentDomain.AssemblyResolve += this.OnAssemblyResolve; this.Plugins = this.LoadPlugins(); @@ -103,6 +109,7 @@ private static string[] GetFolders() /// The of modules private ReadOnlyCollection LoadPlugins() { + this.discoveredAssemblies.Clear(); var sw = Stopwatch.StartNew(); var result = new List(); @@ -116,8 +123,11 @@ private ReadOnlyCollection LoadPlugins() // load all assemblies types encountered in the plugin folders that implement the IAuthenticatorPlugin interface foreach (var pluginFolder in pluginFolders) { - foreach (var assembly in new DirectoryInfo(pluginFolder).GetFiles().Where(file => file.Extension == ".dll") - .Select(file => Assembly.LoadFile(file.FullName))) + var assemblies = new DirectoryInfo(pluginFolder).GetFiles().Where(file => file.Extension == ".dll") + .Select(file => Assembly.LoadFile(file.FullName)) + .ToList(); + + foreach (var assembly in assemblies) { builder.RegisterAssemblyTypes(assembly) .Where(x => typeof(IAuthenticatorPlugin).IsAssignableFrom(x)) @@ -125,6 +135,8 @@ private ReadOnlyCollection LoadPlugins() .PropertiesAutowired() .SingleInstance(); } + + this.discoveredAssemblies.AddRange(assemblies); } var container = builder.Build(); @@ -138,5 +150,25 @@ private ReadOnlyCollection LoadPlugins() return result.AsReadOnly(); } + + /// + /// Helps resolving assemblies that may be required for loaded plugins + /// + /// The sender object + /// The + /// The resolved assemblies, if found + private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) + { + return this.discoveredAssemblies.FirstOrDefault(x => x.FullName == args.Name); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + AppDomain.CurrentDomain.AssemblyResolve -= this.OnAssemblyResolve; + } } } +