using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SQLVision.Core.Enums; using SQLVision.Core.Interfaces; using SQLVision.Core.Models; using System.Reflection; namespace SQLVision.Services.Services; public class PluginManager : IPluginManager { private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private readonly List _plugins = new(); public PluginManager(ILogger logger, IServiceProvider serviceProvider) { _logger = logger; _serviceProvider = serviceProvider; } public void LoadPlugins(string pluginsDirectory) { if (!Directory.Exists(pluginsDirectory)) { Directory.CreateDirectory(pluginsDirectory); _logger.LogInformation("Created plugins directory: {Directory}", pluginsDirectory); return; } var pluginFiles = Directory.GetFiles(pluginsDirectory, "*.dll"); _logger.LogInformation("Found {Count} plugin files", pluginFiles.Length); foreach (var pluginFile in pluginFiles) { try { var assembly = Assembly.LoadFrom(pluginFile); var pluginTypes = assembly.GetTypes() .Where(t => typeof(ISqlVisionPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var pluginType in pluginTypes) { try { var plugin = (ISqlVisionPlugin)Activator.CreateInstance(pluginType)!; var context = new PluginContext(_serviceProvider); plugin.InitializeAsync(context).Wait(); _plugins.Add(plugin); _logger.LogInformation("Loaded plugin: {Name} v{Version}", plugin.Name, plugin.Version); } catch (Exception ex) { _logger.LogError(ex, "Failed to initialize plugin from type {Type}", pluginType.FullName); } } } catch (Exception ex) { _logger.LogError(ex, "Failed to load plugin from {File}", pluginFile); } } } public IEnumerable GetPlugins() => _plugins.AsReadOnly(); public T? GetPlugin() where T : ISqlVisionPlugin => _plugins.OfType().FirstOrDefault(); public async Task BeforeExecutionAsync(ScriptMetadata script, Dictionary parameters) { foreach (var plugin in _plugins) { try { await plugin.InitializeAsync(new PluginContext(_serviceProvider)); // TODO: Добавить метод BeforeExecution в ISqlVisionPlugin если нужно } catch (Exception ex) { _logger.LogError(ex, "Error in plugin {Plugin} BeforeExecution", plugin.Name); } } } public async Task AfterExecutionAsync(ScriptMetadata script, ExecutionResult result) { foreach (var plugin in _plugins) { try { // TODO: Добавить метод AfterExecution в ISqlVisionPlugin если нужно } catch (Exception ex) { _logger.LogError(ex, "Error in plugin {Plugin} AfterExecution", plugin.Name); } } } private class PluginContext : IPluginContext { public IServiceProvider ServiceProvider { get; } public IConfiguration Configuration { get; } public ILogger Logger { get; } public PluginContext(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; Configuration = serviceProvider.GetRequiredService(); Logger = serviceProvider.GetRequiredService>(); } public Task ShowNotificationAsync(string message, NotificationType type) { // TODO: Реализовать показ уведомлений через UI Logger.LogInformation("Plugin notification ({Type}): {Message}", type, message); return Task.CompletedTask; } } }