diff --git a/PluginManager.Test/PluginManager.Test.csproj b/PluginManager.Test/PluginManager.Test.csproj
deleted file mode 100644
index 5e0573b..0000000
--- a/PluginManager.Test/PluginManager.Test.csproj
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- netcoreapp3.1
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/PluginManager.Test/PluginManager.cs b/PluginManager.Test/PluginManager.cs
deleted file mode 100644
index ec7b5af..0000000
--- a/PluginManager.Test/PluginManager.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System;
-using Xunit;
-using PluginManager.Manager;
-using TestPlugin;
-
-namespace PluginManager.Test
-{
- public class PDM : PluginDataManager
- {
- public override PluginData LoadData(string pluginDataFolder)
- {
- return null;
- }
-
- public override void SaveData(string yes, PluginData data)
- {
-
- }
- }
-
- class PPD : PluginProcessData
- {
-
- }
-
- public class PluginManagerTest
- {
- [Fact]
- public void Test1()
- {
- PluginManager pluginManager = new PluginManager();
- PluginManagerConfig.PluginFolderPath = "Plugins";
- pluginManager.Load();
- pluginManager.DoProcessing(new PPD());
- pluginManager.Unload();
- }
- }
-}
diff --git a/PluginManager/PluginManager.csproj b/PluginManager.csproj
similarity index 100%
rename from PluginManager/PluginManager.csproj
rename to PluginManager.csproj
diff --git a/PluginManager/Manager/PluginManager.cs b/PluginManager/Manager/PluginManager.cs
deleted file mode 100644
index 6da8f9b..0000000
--- a/PluginManager/Manager/PluginManager.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-using Crayon;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-
-namespace PluginManager.Manager
-{
- ///
- /// Class that handles all plugin handling
- ///
- /// Type of the Plugin that is going to get loaded
- /// Type of PluginDataManager that is going to get used to load data
- public class PluginManager where T : Plugin where M : PluginDataManager
- {
- ///
- /// A list of plugins based on their name
- ///
- public List Plugins { get; private set; }
-
- private int pluginsSize;
-
- private PluginDataManager dataManager;
-
- ///
- /// Specifies if you are using the plugin system or not
- ///
- public bool Enabled { get; set; }
-
- public PluginManager()
- {
- Plugins = new List();
- dataManager = (PluginDataManager)Activator.CreateInstance(typeof(M), null);
- Enabled = true; // By default it's true
- }
-
- ///
- /// Loads all plugins and their data from the plugin folder
- ///
- public void Load()
- {
- if (Enabled)
- {
- if (string.IsNullOrEmpty(PluginManagerConfig.PluginFolderPath))
- throw new ArgumentNullException("Plugins folder path", "You need to set a path for your plugins folder");
-
- // First run
- if (!Directory.Exists(PluginManagerConfig.PluginFolderPath))
- {
- Directory.CreateDirectory(PluginManagerConfig.PluginFolderPath);
- return; // Let's return here, no plugins available
- }
-
- // Ignores files in this folder
- var pluginDirectories = Directory.GetDirectories(PluginManagerConfig.PluginFolderPath);
-
- foreach (var pluginPath in pluginDirectories)
- {
- // Should contain the plugin file
- var files = Directory.GetFiles(pluginPath, "*.dll");
- foreach (var dll in files)
- {
- try
- {
- // We try to load them if they have at least one class that inherits Plugin
- var assembly = Assembly.LoadFrom(dll);
-
- var types = assembly.GetTypes();
-
- foreach (var type in types)
- {
- if (type.IsSubclassOf(typeof(T)))
- addPlugin(type);
- }
- }
- catch (ReflectionTypeLoadException ex)
- {
- Console.Error.WriteLine(Output.Red($"Failed to load {Path.GetFileName(dll)}. We will continue to load more assemblies"), ex);
- }
- catch (Exception ex)
- {
- Console.Error.WriteLine(Output.Red($"Failed to load {Path.GetFileName(dll)}. We will continue to load more assemblies"), ex);
- }
- }
- }
-
- pluginsSize = Plugins.Count;
- }
- else
- {
- // Throw here?
- }
- }
-
- ///
- /// Saves plugin information to their data files
- ///
- public void Unload()
- {
- foreach (var plugin in Plugins)
- {
- try
- {
- var dataFilePath = plugin.DataFilePath();
-
- // If it's null it means it's not using a file
- if (!string.IsNullOrEmpty(dataFilePath))
- dataManager.SaveData(dataFilePath, plugin.Data);
- }
- catch (Exception)
- {
- Console.Error.WriteLine(Output.Red($"Couldn't save data for {plugin.Name()}"));
- }
- }
- }
-
- ///
- /// Internal function that handles plugin instancing
- ///
- ///
- internal void addPlugin(Type plugin)
- {
- Plugin pluginInstance = (T)Activator.CreateInstance(plugin);
-
- try
- {
- Plugins.Add((T)pluginInstance);
-
- var pluginDataFilePath = pluginInstance.DataFilePath();
-
- // If it's null we are not using plugin data
- if (!string.IsNullOrEmpty(PluginManagerConfig.PluginDataFolderPath) && !string.IsNullOrEmpty(pluginDataFilePath))
- {
- var pluginData = dataManager.LoadData(Path.Combine(PluginManagerConfig.PluginDataFolderPath, pluginDataFilePath));
-
- // This one shouldn't throw, loadData() will always exist
- pluginInstance.loadData(pluginData);
- }
-
- Console.WriteLine($"Loaded {pluginInstance.Name()}");
- }
- catch (ArgumentException)
- {
- Console.Error.WriteLine(Output.Red($"{pluginInstance.Name()} is already loaded"));
- }
- }
-
- ///
- /// Executes DoProcessing on all plugins
- ///
- ///
- public void DoProcessing(PluginProcessData processData)
- {
- for (int i = 0; i < pluginsSize; i++)
- {
- Plugins[i].DoProcessing(processData);
- }
- }
- }
-}
diff --git a/TestPlugin/Class1.cs b/TestPlugin/Class1.cs
deleted file mode 100644
index 7023502..0000000
--- a/TestPlugin/Class1.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using PluginManager;
-using System;
-
-namespace TestPlugin
-{
- public abstract class Class1 : Plugin
- {
- public Class1()
- {
- }
- }
-
- public class asd : Class1
- {
- public asd()
- {
- base.OnLoaded += Asd_OnLoaded;
- }
-
- private void Asd_OnLoaded(PluginData data)
- {
- Console.Out.WriteLine("I'm loaded man");
- }
-
- public override void DoProcessing(PluginProcessData data)
- {
- //Console.WriteLine("working");
- }
-
- public override string Name()
- {
- return "asd";
- }
-
- public override Version Version()
- {
- return new Version("1.0.0.0");
- }
-
- public override void BuildDataFile()
- {
- // Leave this empty if you are not using a data file
- }
-
- public override string DataFilePath()
- {
- return null;
- }
- }
-}
diff --git a/TestPlugin/TestPlugin.csproj b/TestPlugin/TestPlugin.csproj
deleted file mode 100644
index 87fe537..0000000
--- a/TestPlugin/TestPlugin.csproj
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- netcoreapp3.1
-
-
-
- ..\PluginManager.Test\bin\Debug\Plugins\Yep\
-
-
-
-
-
-
-
diff --git a/src/Manager/PluginClassManager.cs b/src/Manager/PluginClassManager.cs
new file mode 100644
index 0000000..7d7348f
--- /dev/null
+++ b/src/Manager/PluginClassManager.cs
@@ -0,0 +1,39 @@
+using Crayon;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace PluginManager.Manager
+{
+ public class PluginClassManager : PluginManagerBase where T : Plugin where M : PluginDataManager
+ where R : PluginResponseData where P : PluginProcessData
+ {
+ ///
+ /// Loads all plugins and their data from the plugin folder
+ ///
+ public override void Load()
+ {
+ if (Enabled)
+ {
+ // Is this slow?
+ // I mean.... will this work
+ Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
+ foreach (var assembly in assemblies)
+ {
+ var types = assembly.GetTypes();
+ foreach (Type type in types)
+ {
+ if (type.IsSubclassOf(typeof(T)))
+ addPlugin(type);
+ }
+ }
+
+ // It's faster if we store them instead of accessing the property
+ pluginsSize = Plugins.Count;
+ }
+ }
+ }
+}
diff --git a/PluginManager/Manager/PluginDataManager.cs b/src/Manager/PluginDataManager.cs
similarity index 100%
rename from PluginManager/Manager/PluginDataManager.cs
rename to src/Manager/PluginDataManager.cs
diff --git a/src/Manager/PluginDllManager.cs b/src/Manager/PluginDllManager.cs
new file mode 100644
index 0000000..b93e4af
--- /dev/null
+++ b/src/Manager/PluginDllManager.cs
@@ -0,0 +1,74 @@
+using Crayon;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace PluginManager.Manager
+{
+ ///
+ /// Class that handles all plugin handling
+ ///
+ /// Type of the Plugin that is going to get loaded
+ /// Type of PluginDataManager that is going to get used to load data
+ /// Type of PluginResponseData that is going to get used to return a response from the plugin list
+ /// Type of PluginProcess data that is going to get used to process data
+ public class PluginDllManager : PluginManagerBase where T : Plugin where M : PluginDataManager
+ where R : PluginResponseData where P : PluginProcessData
+ {
+ ///
+ /// Loads all plugins and their data from the plugin folder
+ ///
+ public override void Load()
+ {
+ if (Enabled)
+ {
+ if (string.IsNullOrEmpty(PluginManagerConfig.PluginFolderPath))
+ throw new ArgumentNullException("Plugins folder path", "You need to set a path for your plugins folder");
+
+ // First run
+ if (!Directory.Exists(PluginManagerConfig.PluginFolderPath))
+ {
+ Directory.CreateDirectory(PluginManagerConfig.PluginFolderPath);
+ return; // Let's return here, no plugins available
+ }
+
+ // Ignores files in this folder
+ var pluginDirectories = Directory.GetDirectories(PluginManagerConfig.PluginFolderPath);
+
+ foreach (var pluginPath in pluginDirectories)
+ {
+ // Should contain the plugin file
+ var files = Directory.GetFiles(pluginPath, "*.dll");
+
+ // If it doesn't contain anything, this will not run
+ foreach (var dll in files)
+ {
+ try
+ {
+ // We try to load them if they have at least one class that inherits Plugin
+ var assembly = Assembly.LoadFrom(dll);
+
+ var types = assembly.GetTypes();
+
+ foreach (var type in types)
+ {
+ if (type.IsSubclassOf(typeof(T)))
+ addPlugin(type);
+ }
+ }
+ catch (ReflectionTypeLoadException ex)
+ {
+ Console.Error.WriteLine(Output.Red($"Failed to load {Path.GetFileName(dll)}. We will continue to load more assemblies"), ex);
+ }
+ }
+ }
+
+ // It's faster if we store them instead of accessing the property
+ pluginsSize = Plugins.Count;
+ }
+ }
+ }
+}
diff --git a/src/Manager/PluginManagerBase.cs b/src/Manager/PluginManagerBase.cs
new file mode 100644
index 0000000..650867d
--- /dev/null
+++ b/src/Manager/PluginManagerBase.cs
@@ -0,0 +1,112 @@
+using Crayon;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace PluginManager.Manager
+{
+ public abstract class PluginManagerBase where T : Plugin where M : PluginDataManager
+ where R : PluginResponseData where P : PluginProcessData
+ {
+ public PluginManagerBase()
+ {
+ DataManager = (M)Activator.CreateInstance(typeof(M), null);
+ Plugins = new List();
+ Enabled = true; // By default it's true
+ }
+
+ ///
+ /// Data manager object
+ ///
+ internal M DataManager { get; set; }
+
+ ///
+ /// A list of plugins based on their name
+ ///
+ public List Plugins { get; internal set; }
+
+ internal int pluginsSize;
+
+ ///
+ /// Specifies if you are using the plugin system or not
+ ///
+ public bool Enabled { get; set; }
+
+ public abstract void Load();
+
+ public virtual void Unload()
+ {
+ foreach (var plugin in Plugins)
+ {
+ try
+ {
+ plugin.InvokeOnUnload();
+
+ if (plugin.UsingDataFile())
+ {
+ var dataFilePath = plugin.DataFileName();
+ DataManager.SaveData(dataFilePath, plugin.Data);
+ }
+ }
+ catch (Exception)
+ {
+ Console.Error.WriteLine(Output.Red($"Couldn't save data for {plugin.Name()}"));
+ }
+ }
+ }
+
+ ///
+ /// Executes DoProcessing on all plugins
+ ///
+ ///
+ /// The response object
+ public virtual R DoProcessing(P processData)
+ {
+ R response = (R)Activator.CreateInstance(typeof(R));
+ for (int i = 0; i < pluginsSize; i++)
+ {
+ Plugins[i].DoProcessing(processData, ref response);
+ }
+
+ return response;
+ }
+
+ ///
+ /// Internal function that handles plugin instancing
+ ///
+ ///
+ internal void addPlugin(Type type)
+ {
+ Plugin plugin = (T)Activator.CreateInstance(type);
+
+ var pluginName = plugin.Name();
+
+ // check versions too?
+ // and load the most recent one?
+ for (int i = 0; i < pluginsSize; i++)
+ {
+ if (Plugins[i].Name() == pluginName)
+ {
+ Console.Error.WriteLine(Output.Red($"{pluginName} is already loaded"));
+ return;
+ }
+ }
+
+ Plugins.Add((T)plugin);
+
+ if (plugin.UsingDataFile())
+ {
+ var pluginDataFilePath = plugin.DataFileName();
+ if (string.IsNullOrEmpty(pluginDataFilePath))
+ throw new ArgumentNullException("Plugin Data File Path", "To use data files you must specify a name for the file");
+
+ var pluginData = DataManager.LoadData(Path.Combine(PluginManagerConfig.PluginDataFolderPath, pluginDataFilePath));
+
+ plugin.loadData(pluginData);
+ }
+
+ Console.WriteLine($"Loaded {pluginName}");
+ }
+ }
+}
diff --git a/PluginManager/Plugin/Plugin.cs b/src/Plugin/Plugin.cs
similarity index 58%
rename from PluginManager/Plugin/Plugin.cs
rename to src/Plugin/Plugin.cs
index da53ba7..a012a45 100644
--- a/PluginManager/Plugin/Plugin.cs
+++ b/src/Plugin/Plugin.cs
@@ -4,18 +4,30 @@ using System.Text;
namespace PluginManager
{
+ public delegate void OnLoadEvent();
public delegate void OnLoadedEvent(PluginData data);
+ public delegate void OnUnloadEvent();
///
/// Base class to create plugins
///
- public abstract class Plugin
+ public abstract class Plugin where R : PluginResponseData where P : PluginProcessData
{
+ ///
+ /// Event executed when plugin object is instanciated
+ ///
+ public event OnLoadEvent OnLoad;
+
///
/// Event executed when the plugin manager finishes loading this plugin
///
public event OnLoadedEvent OnLoaded;
+ ///
+ /// Event executed when DataManager starts unloading the plugin
+ ///
+ public event OnUnloadEvent OnUnload;
+
///
/// The plugin data object
///
@@ -23,7 +35,12 @@ namespace PluginManager
public Plugin()
{
- // Need a constructor to use Activator.CreateInstance()
+ OnLoad?.Invoke();
+ }
+
+ internal void InvokeOnUnload()
+ {
+ OnUnload?.Invoke();
}
///
@@ -32,8 +49,6 @@ namespace PluginManager
/// Data object that is going to get loaded
internal void loadData(PluginData data)
{
- if (data == null)
- BuildDataFile();
this.Data = data;
OnLoaded?.Invoke(data);
}
@@ -55,16 +70,24 @@ namespace PluginManager
/// The name of the plugin
public abstract string Name();
+ ///
+ /// Specifies whether we are using a data file or not
+ ///
+ /// Whether we are using a data file or not
+ public abstract bool UsingDataFile();
+
///
/// The path to the plugin data file
///
/// The path to the plugin data file
- public abstract string DataFilePath();
+ public abstract string DataFileName();
///
/// Base function that should get called everytime this plugin needs to process data
///
- ///
- public abstract void DoProcessing(PluginProcessData data);
+ /// The data the plugin needs to do processing
+ /// Response object that the plugin will append to
+ /// The same object that is passed to the response parameter
+ public abstract ref R DoProcessing(P data, ref R response);
}
}
diff --git a/PluginManager/Plugin/PluginData.cs b/src/Plugin/PluginData.cs
similarity index 100%
rename from PluginManager/Plugin/PluginData.cs
rename to src/Plugin/PluginData.cs
diff --git a/PluginManager/Plugin/PluginProcessData.cs b/src/Plugin/PluginProcessData.cs
similarity index 100%
rename from PluginManager/Plugin/PluginProcessData.cs
rename to src/Plugin/PluginProcessData.cs
diff --git a/src/Plugin/PluginResponseData.cs b/src/Plugin/PluginResponseData.cs
new file mode 100644
index 0000000..faf25a5
--- /dev/null
+++ b/src/Plugin/PluginResponseData.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PluginManager
+{
+ public abstract class PluginResponseData
+ {
+ }
+}
diff --git a/PluginManager/PluginConfig.cs b/src/PluginConfig.cs
similarity index 54%
rename from PluginManager/PluginConfig.cs
rename to src/PluginConfig.cs
index 8120d3e..aa65f26 100644
--- a/PluginManager/PluginConfig.cs
+++ b/src/PluginConfig.cs
@@ -6,7 +6,14 @@ namespace PluginManager
{
public static class PluginManagerConfig
{
+ ///
+ /// Path to the folder where plugin data is going to be stored
+ ///
public static string PluginDataFolderPath { get; set; }
+
+ ///
+ /// Path to the folder where plugins are going to be stored
+ ///
public static string PluginFolderPath { get; set; }
}
}