more methods to load plugins
This commit is contained in:
13
Pilz.Plugins.Advanced/IPluginFeatureProvider.cs
Normal file
13
Pilz.Plugins.Advanced/IPluginFeatureProvider.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pilz.Plugins.Advanced
|
||||
{
|
||||
public interface IPluginFeatureProvider<T> where T : PluginFeature
|
||||
{
|
||||
static abstract T Instance { get; }
|
||||
}
|
||||
}
|
||||
13
Pilz.Plugins.Advanced/IPluginFeaturesProvider.cs
Normal file
13
Pilz.Plugins.Advanced/IPluginFeaturesProvider.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Pilz.Plugins.Advanced
|
||||
{
|
||||
public interface IPluginFeaturesProvider
|
||||
{
|
||||
static abstract PluginFeature[] GetFeatures();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -9,38 +10,72 @@ namespace Pilz.Plugins
|
||||
{
|
||||
public class PluginManager<TPluginInterface, TPluginRuntimeInfo> where TPluginInterface : class where TPluginRuntimeInfo : PluginRuntimeInfo<TPluginInterface>
|
||||
{
|
||||
public IEnumerable<TPluginRuntimeInfo> LoadPlugins(string[] paths)
|
||||
private readonly List<TPluginRuntimeInfo> loadedPlugins = [];
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all currently loaded plugins.
|
||||
/// </summary>
|
||||
public IEnumerable<TPluginRuntimeInfo> LoadedPlugins => loadedPlugins.AsReadOnly();
|
||||
|
||||
private void CurrentDomain_AssemblyLoad(object? sender, AssemblyLoadEventArgs args)
|
||||
{
|
||||
return LoadPlugins(paths, null);
|
||||
LoadPlugin(args.LoadedAssembly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads assembly from the given file paths and then loads the plugins from the assemblies.
|
||||
/// </summary>
|
||||
/// <param name="paths"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<TPluginRuntimeInfo> LoadPlugins(string[] paths, params object?[]? parameters)
|
||||
{
|
||||
var states = new List<TPluginRuntimeInfo>();
|
||||
|
||||
foreach (string path in paths)
|
||||
states.Add(LoadPlugin(path));
|
||||
|
||||
return states;
|
||||
foreach (var path in paths)
|
||||
yield return LoadPlugin(path, parameters);
|
||||
}
|
||||
|
||||
public TPluginRuntimeInfo LoadPlugin(string path)
|
||||
/// <summary>
|
||||
/// Loads plugins from the given assemblies.
|
||||
/// </summary>
|
||||
/// <param name="paths"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<TPluginRuntimeInfo> LoadPlugins(Assembly[] assemblies, params object?[]? parameters)
|
||||
{
|
||||
return LoadPlugin(path, null);
|
||||
foreach (var assembly in assemblies)
|
||||
yield return LoadPlugin(assembly, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads plugins from already loaded assemblies for the current <see cref="AppDomain.CurrentDomain"/>.
|
||||
/// </summary>
|
||||
/// <param name="listenAssemblyLoadContext">Do also load plugins from all yet not loaded assemblies by listening the event <see cref="AppDomain.AssemblyLoad"/>.
|
||||
/// <returns></returns>
|
||||
public IEnumerable<TPluginRuntimeInfo> LoadOwnPlugins(bool listenAssemblyLoadContext, params object?[]? parameters)
|
||||
{
|
||||
if (listenAssemblyLoadContext)
|
||||
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
|
||||
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
yield return LoadPlugin(assembly, parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads an assembly from the given file path and then loads the plugin from the assembly.
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public TPluginRuntimeInfo LoadPlugin(string path, params object?[]? parameters)
|
||||
{
|
||||
var info = Activator.CreateInstance<TPluginRuntimeInfo>();
|
||||
var irmplugin = typeof(TPluginInterface);
|
||||
var loadContext = new PluginLoadContext(path);
|
||||
Assembly? assembly = null;
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
assembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path)));
|
||||
info.Assembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path)));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -50,9 +85,37 @@ namespace Pilz.Plugins
|
||||
else
|
||||
info.Status = PluginStatus.FileNotFound;
|
||||
|
||||
if (assembly != null)
|
||||
if (info.Assembly != null)
|
||||
info = LoadPlugin(info.Assembly, parameters);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the plugin from a given assembly.
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
public TPluginRuntimeInfo LoadPlugin(Assembly assembly, params object?[]? parameters)
|
||||
{
|
||||
foreach (var type in assembly.GetTypes())
|
||||
var info = Activator.CreateInstance<TPluginRuntimeInfo>();
|
||||
info.Assembly = assembly;
|
||||
LoadPlugin(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
private void LoadPlugin(TPluginRuntimeInfo info, params object?[]? parameters)
|
||||
{
|
||||
var irmplugin = typeof(TPluginInterface);
|
||||
|
||||
if (info.Assembly == null)
|
||||
info.Status = PluginStatus.NoValidPlugin;
|
||||
else if (loadedPlugins.Any(n => n.Assembly == info.Assembly))
|
||||
info.Status = PluginStatus.AlreadyLoaded;
|
||||
else
|
||||
{
|
||||
foreach (var type in info.Assembly.GetTypes())
|
||||
{
|
||||
if (info.Plugin == null && irmplugin.IsAssignableFrom(type))
|
||||
{
|
||||
@@ -62,6 +125,7 @@ namespace Pilz.Plugins
|
||||
{
|
||||
info.Plugin = plugin;
|
||||
info.Status = PluginStatus.Success;
|
||||
loadedPlugins.Add(info);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -70,12 +134,10 @@ namespace Pilz.Plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.Plugin == null)
|
||||
info.Status = PluginStatus.NoValidPlugin;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -10,5 +11,6 @@ namespace Pilz.Plugins
|
||||
{
|
||||
public T? Plugin { get; internal set; }
|
||||
public PluginStatus Status { get; internal set; }
|
||||
public Assembly? Assembly { get; internal set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Pilz.Plugins
|
||||
{
|
||||
None,
|
||||
Success,
|
||||
AlreadyLoaded,
|
||||
FileNotFound,
|
||||
ErrorAtLoading,
|
||||
ErrorAtInitializing,
|
||||
|
||||
Reference in New Issue
Block a user