MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.Analysis/Infrastructure/PluginDiscoveryService.cs

178 lines
6.6 KiB
C#
Executable File

using MarketAlly.AIPlugin;
using MarketAlly.AIPlugin.Analysis.Plugins;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace MarketAlly.AIPlugin.Analysis.Infrastructure
{
/// <summary>
/// Service for discovering and loading analysis plugins
/// </summary>
public class PluginDiscoveryService : IPluginDiscovery
{
private readonly ILogger<PluginDiscoveryService>? _logger;
public PluginDiscoveryService(ILogger<PluginDiscoveryService>? logger = null)
{
_logger = logger;
}
public Task<IEnumerable<IAIPlugin>> DiscoverPluginsAsync(string pluginDirectory)
{
_logger?.LogInformation("Discovering plugins in directory: {PluginDirectory}", pluginDirectory);
var plugins = new List<IAIPlugin>();
if (!Directory.Exists(pluginDirectory))
{
_logger?.LogWarning("Plugin directory does not exist: {PluginDirectory}", pluginDirectory);
return Task.FromResult<IEnumerable<IAIPlugin>>(plugins);
}
var assemblyFiles = Directory.GetFiles(pluginDirectory, "*.dll", SearchOption.AllDirectories);
foreach (var assemblyFile in assemblyFiles)
{
try
{
var assembly = Assembly.LoadFrom(assemblyFile);
var pluginTypes = assembly.GetTypes()
.Where(t => typeof(IAIPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
foreach (var pluginType in pluginTypes)
{
try
{
var plugin = Activator.CreateInstance(pluginType) as IAIPlugin;
if (plugin != null && ValidatePlugin(plugin))
{
plugins.Add(plugin);
_logger?.LogDebug("Loaded plugin: {PluginType} from {AssemblyFile}",
pluginType.Name, assemblyFile);
}
}
catch (Exception ex)
{
_logger?.LogError(ex, "Failed to create instance of plugin type: {PluginType}",
pluginType.Name);
}
}
}
catch (Exception ex)
{
_logger?.LogError(ex, "Failed to load assembly: {AssemblyFile}", assemblyFile);
}
}
_logger?.LogInformation("Discovered {PluginCount} plugins", plugins.Count);
return Task.FromResult<IEnumerable<IAIPlugin>>(plugins);
}
public Task<IAIPlugin> LoadPluginAsync(string assemblyPath, string typeName)
{
_logger?.LogInformation("Loading specific plugin: {TypeName} from {AssemblyPath}",
typeName, assemblyPath);
if (!File.Exists(assemblyPath))
{
throw new FileNotFoundException($"Assembly file not found: {assemblyPath}");
}
var assembly = Assembly.LoadFrom(assemblyPath);
var pluginType = assembly.GetType(typeName);
if (pluginType == null)
{
throw new TypeLoadException($"Type not found: {typeName}");
}
if (!typeof(IAIPlugin).IsAssignableFrom(pluginType))
{
throw new InvalidOperationException($"Type does not implement IAIPlugin: {typeName}");
}
var plugin = Activator.CreateInstance(pluginType) as IAIPlugin;
if (plugin == null)
{
throw new InvalidOperationException($"Failed to create instance of type: {typeName}");
}
if (!ValidatePlugin(plugin))
{
throw new InvalidOperationException($"Plugin validation failed: {typeName}");
}
_logger?.LogInformation("Successfully loaded plugin: {TypeName}", typeName);
return Task.FromResult(plugin);
}
public IEnumerable<IAIPlugin> GetBuiltInPlugins()
{
_logger?.LogInformation("Getting built-in analysis plugins");
var plugins = new List<IAIPlugin>
{
new PerformanceAnalyzerPlugin(),
new ArchitectureValidatorPlugin(),
new TechnicalDebtPlugin(),
new ComplexityAnalyzerPlugin(),
new TestAnalysisPlugin(),
new BehaviorAnalysisPlugin(),
new SQLiteSchemaReaderPlugin()
};
_logger?.LogInformation("Loaded {PluginCount} built-in plugins", plugins.Count);
return plugins;
}
public bool ValidatePlugin(IAIPlugin plugin)
{
if (plugin == null)
{
_logger?.LogWarning("Plugin is null");
return false;
}
try
{
// Check if plugin has required attributes
var pluginType = plugin.GetType();
var aiPluginAttribute = pluginType.GetCustomAttribute<AIPluginAttribute>();
if (aiPluginAttribute == null)
{
_logger?.LogWarning("Plugin missing AIPluginAttribute: {PluginType}", pluginType.Name);
return false;
}
// Check if SupportedParameters is implemented
if (plugin.SupportedParameters == null)
{
_logger?.LogWarning("Plugin SupportedParameters is null: {PluginType}", pluginType.Name);
return false;
}
// Validate that ExecuteAsync method exists and is properly implemented
var executeMethod = pluginType.GetMethod("ExecuteAsync");
if (executeMethod == null)
{
_logger?.LogWarning("Plugin missing ExecuteAsync method: {PluginType}", pluginType.Name);
return false;
}
_logger?.LogDebug("Plugin validation successful: {PluginType}", pluginType.Name);
return true;
}
catch (Exception ex)
{
_logger?.LogError(ex, "Plugin validation failed: {PluginType}", plugin.GetType().Name);
return false;
}
}
}
}