using System.Reflection; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using StellaOps.Plugin; using StellaOps.Plugin.Hosting; namespace StellaOps.Messaging.Plugins; /// /// Loads and registers messaging transport plugins. /// public sealed class MessagingPluginLoader { private readonly ILogger? _logger; public MessagingPluginLoader(ILogger? logger = null) { _logger = logger; } /// /// Discovers and loads messaging transport plugins from the specified directory. /// public IReadOnlyList LoadFromDirectory( string pluginDirectory, string searchPattern = "StellaOps.Messaging.Transport.*.dll") { if (!Directory.Exists(pluginDirectory)) { _logger?.LogWarning("Plugin directory does not exist: {Directory}", pluginDirectory); return []; } var options = new PluginHostOptions { PluginsDirectory = pluginDirectory, EnsureDirectoryExists = false, RecursiveSearch = false }; options.SearchPatterns.Add(searchPattern); var result = PluginHost.LoadPlugins(options); var plugins = new List(); foreach (var pluginAssembly in result.Plugins) { var transportPlugins = PluginLoader.LoadPlugins(new[] { pluginAssembly.Assembly }); plugins.AddRange(transportPlugins); foreach (var plugin in transportPlugins) { _logger?.LogDebug("Loaded messaging transport plugin: {Name} from {Assembly}", plugin.Name, pluginAssembly.Assembly.GetName().Name); } } return plugins; } /// /// Loads messaging transport plugins from the specified assemblies. /// public IReadOnlyList LoadFromAssemblies(IEnumerable assemblies) { return PluginLoader.LoadPlugins(assemblies); } /// /// Finds and registers the configured transport plugin. /// /// Available plugins. /// Service collection. /// Configuration. /// Configuration section path (default: "messaging"). /// True if a plugin was registered. public bool RegisterConfiguredTransport( IReadOnlyList plugins, IServiceCollection services, IConfiguration configuration, string configSectionPath = "messaging") { var messagingSection = configuration.GetSection(configSectionPath); var transportName = messagingSection.GetValue("transport"); if (string.IsNullOrWhiteSpace(transportName)) { _logger?.LogWarning("No messaging transport configured at {Path}:transport", configSectionPath); return false; } var plugin = plugins.FirstOrDefault(p => string.Equals(p.Name, transportName, StringComparison.OrdinalIgnoreCase)); if (plugin is null) { _logger?.LogError("Messaging transport plugin '{Transport}' not found. Available: {Available}", transportName, string.Join(", ", plugins.Select(p => p.Name))); return false; } var transportConfigSection = $"{configSectionPath}:{transportName}"; var context = new MessagingTransportRegistrationContext( services, configuration, transportConfigSection); plugin.Register(context); _logger?.LogInformation("Registered messaging transport: {Transport}", transportName); return true; } }