Plugins engine is working

This commit is contained in:
Michał Zieliński
2025-06-02 16:54:33 +02:00
parent 8df1b34478
commit 099d72618f
29 changed files with 668 additions and 227 deletions

View File

@@ -10,5 +10,6 @@
<PackageReference Include="Google.Apis.Sheets.v4" Version="1.68.0.3525" />
<PackageReference Include="Google.Apis.Auth" Version="1.68.0" />
<PackageReference Include="AngouriMath" Version="1.4.0-preview.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,10 @@
using DiunaBI.Core.Models;
namespace DiunaBI.Core.Interfaces;
public interface IDataExporter
{
string ExporterType { get; }
bool CanExport(string exporterType);
void Export(Layer layer);
}

View File

@@ -0,0 +1,11 @@
using DiunaBI.Core.Models;
namespace DiunaBI.Core.Interfaces;
public interface IDataImporter
{
string ImporterType { get; }
bool CanImport(string importerType);
void Import(Layer importWorker);
}

View File

@@ -0,0 +1,11 @@
using DiunaBI.Core.Models;
namespace DiunaBI.Core.Interfaces;
public interface IDataProcessor
{
string ProcessorType { get; }
bool CanProcess(string processorType);
void Process(Layer processWorker);
}

View File

@@ -0,0 +1,12 @@
namespace DiunaBI.Core.Interfaces;
public interface IPlugin
{
string Name { get; }
string Version { get; }
string Author { get; }
string Description { get; }
void Initialize();
void Dispose();
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using DiunaBI.Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace DiunaBI.Core.Services;
public class PluginManager
{
private readonly ILogger<PluginManager> _logger;
private readonly IServiceProvider _serviceProvider;
private readonly List<Type> _processorTypes = new();
private readonly List<Type> _importerTypes = new();
private readonly List<IDataExporter> _exporters = new();
private readonly List<IPlugin> _plugins = new();
public PluginManager(ILogger<PluginManager> logger, IServiceProvider serviceProvider)
{
_logger = logger;
_serviceProvider = serviceProvider;
}
public void LoadPluginsFromDirectory(string pluginsPath)
{
if (!Directory.Exists(pluginsPath))
{
_logger.LogWarning("Plugins directory not found: {Path}", pluginsPath);
return;
}
var dllFiles = Directory.GetFiles(pluginsPath, "*.dll", SearchOption.AllDirectories);
foreach (var dllFile in dllFiles)
{
try
{
LoadPluginFromAssembly(dllFile);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to load plugin from {File}", dllFile);
}
}
_logger.LogInformation("Loaded {ProcessorCount} processors and {ImporterCount} importers from {PluginCount} plugins",
_processorTypes.Count, _importerTypes.Count, _plugins.Count);
}
private void LoadPluginFromAssembly(string assemblyPath)
{
_logger.LogDebug("Loading assembly from: {Path}", assemblyPath); // Information -> Debug
try
{
var assembly = Assembly.LoadFrom(assemblyPath);
_logger.LogDebug("Assembly loaded successfully: {Name}", assembly.FullName); // Information -> Debug
foreach (var type in assembly.GetTypes())
{
if (typeof(IDataProcessor).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
{
_processorTypes.Add(type);
_logger.LogDebug("Registered processor: {Type}", type.Name); // Information -> Debug
}
if (typeof(IDataImporter).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
{
_importerTypes.Add(type);
_logger.LogDebug("Registered importer: {Type}", type.Name); // Information -> Debug
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to load assembly from {Path}", assemblyPath); // ZOSTAW jako Error
}
}
public IDataProcessor? GetProcessor(string processorType)
{
foreach (var type in _processorTypes)
{
try
{
using var scope = _serviceProvider.CreateScope();
var instance = (IDataProcessor)ActivatorUtilities.CreateInstance(scope.ServiceProvider, type);
if (instance.CanProcess(processorType))
{
var scopedProvider = _serviceProvider.CreateScope().ServiceProvider;
return (IDataProcessor)ActivatorUtilities.CreateInstance(scopedProvider, type);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to create processor instance of type {Type}", type.Name);
}
}
return null;
}
public IDataImporter? GetImporter(string importerType)
{
foreach (var type in _importerTypes)
{
try
{
using var scope = _serviceProvider.CreateScope();
var instance = (IDataImporter)ActivatorUtilities.CreateInstance(scope.ServiceProvider, type);
if (instance.CanImport(importerType))
{
var scopedProvider = _serviceProvider.CreateScope().ServiceProvider;
return (IDataImporter)ActivatorUtilities.CreateInstance(scopedProvider, type);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to create importer instance of type {Type}", type.Name);
}
}
return null;
}
public IDataExporter? GetExporter(string exporterType)
{
return _exporters.FirstOrDefault(e => e.CanExport(exporterType));
}
public IEnumerable<IDataExporter> GetAllExporters() => _exporters.AsReadOnly();
public IEnumerable<IPlugin> GetAllPlugins() => _plugins.AsReadOnly();
}