From 65237f84a22a561d719f57ffb1cc8013f70f20ef Mon Sep 17 00:00:00 2001 From: Exter-N Date: Mon, 10 Nov 2025 04:41:01 +0100 Subject: [PATCH] Add functions to get a plugin by assembly This is intended for advanced IPC scenarios, for example, accepting a delegate or an object and identifying which plugin it originates from, in order to display integration information to the user, and/or to release references when the originating plugin is unloaded/reloaded if it forgot to clean after itself. --- Dalamud/Plugin/DalamudPluginInterface.cs | 25 ++++++++++++++++++++ Dalamud/Plugin/IDalamudPluginInterface.cs | 16 +++++++++++++ Dalamud/Plugin/Internal/Types/LocalPlugin.cs | 9 +++++++ 3 files changed, 50 insertions(+) diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 39a4e7e4b..957e8080a 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.Loader; using System.Threading.Tasks; using Dalamud.Configuration; @@ -269,6 +270,30 @@ internal sealed class DalamudPluginInterface : IDalamudPluginInterface, IDisposa return true; } + /// + /// Gets the plugin the given assembly is part of. + /// + /// The assembly to check. + /// The plugin the given assembly is part of, or null if this is a shared assembly or if this information cannot be determined. + public IExposedPlugin? GetPlugin(Assembly assembly) + => AssemblyLoadContext.GetLoadContext(assembly) switch + { + null => null, + var context => this.GetPlugin(context), + }; + + /// + /// Gets the plugin that loads in the given context. + /// + /// The context to check. + /// The plugin that loads in the given context, or null if this isn't a plugin's context or if this information cannot be determined. + public IExposedPlugin? GetPlugin(AssemblyLoadContext context) + => Service.Get().InstalledPlugins.FirstOrDefault(p => p.LoadsIn(context)) switch + { + null => null, + var p => new ExposedPlugin(p), + }; + #region IPC /// diff --git a/Dalamud/Plugin/IDalamudPluginInterface.cs b/Dalamud/Plugin/IDalamudPluginInterface.cs index b8ab55450..e1dd34f87 100644 --- a/Dalamud/Plugin/IDalamudPluginInterface.cs +++ b/Dalamud/Plugin/IDalamudPluginInterface.cs @@ -1,6 +1,8 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Reflection; +using System.Runtime.Loader; using System.Threading.Tasks; using Dalamud.Configuration; @@ -180,6 +182,20 @@ public interface IDalamudPluginInterface /// Returns false if the DalamudInterface was null. bool OpenDeveloperMenu(); + /// + /// Gets the plugin the given assembly is part of. + /// + /// The assembly to check. + /// The plugin the given assembly is part of, or null if this is a shared assembly or if this information cannot be determined. + IExposedPlugin? GetPlugin(Assembly assembly); + + /// + /// Gets the plugin that loads in the given context. + /// + /// The context to check. + /// The plugin that loads in the given context, or null if this isn't a plugin's context or if this information cannot be determined. + IExposedPlugin? GetPlugin(AssemblyLoadContext context); + /// T GetOrCreateData(string tag, Func dataGenerator) where T : class; diff --git a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs index da8ec8ff9..0197683ef 100644 --- a/Dalamud/Plugin/Internal/Types/LocalPlugin.cs +++ b/Dalamud/Plugin/Internal/Types/LocalPlugin.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Runtime.ExceptionServices; +using System.Runtime.Loader; using System.Threading; using System.Threading.Tasks; @@ -553,6 +554,14 @@ internal class LocalPlugin : IAsyncDisposable }); } + /// + /// Checks whether this plugin loads in the given load context. + /// + /// The load context to check. + /// Whether this plugin loads in the given load context. + public bool LoadsIn(AssemblyLoadContext context) + => this.loader?.LoadContext == context; + /// /// Save this plugin manifest. ///