improve plugin load

This commit is contained in:
schedpas
2024-04-18 06:28:40 +02:00
parent efb0636312
commit eb764da56f
4 changed files with 68 additions and 28 deletions

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Plugins
{
public class PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo> where TPluginInterface : class where TPluginRuntimeInfo : PluginRuntimeInfo<TPluginInterface>
{
internal List<TPluginRuntimeInfo> PluginsInternal { get; } = [];
public Assembly Assembly { get; internal set; }
public PluginLoadStatus Status { get; internal set; }
public IEnumerable<TPluginRuntimeInfo> Plugins => PluginsInternal.AsReadOnly();
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pilz.Plugins
{
public enum PluginLoadStatus
{
None,
Success,
AlreadyLoaded,
ErrorAtLoading,
FileNotFound,
NoValidPlugin
}
}

View File

@@ -28,7 +28,7 @@ namespace Pilz.Plugins
/// <param name="paths"></param> /// <param name="paths"></param>
/// <param name="parameters"></param> /// <param name="parameters"></param>
/// <returns></returns> /// <returns></returns>
public IEnumerable<TPluginRuntimeInfo> LoadPlugins(string[] paths, params object?[]? parameters) public IEnumerable<PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo>> LoadPlugins(string[] paths, params object?[]? parameters)
{ {
foreach (var path in paths) foreach (var path in paths)
yield return LoadPlugin(path, parameters); yield return LoadPlugin(path, parameters);
@@ -40,7 +40,7 @@ namespace Pilz.Plugins
/// <param name="paths"></param> /// <param name="paths"></param>
/// <param name="parameters"></param> /// <param name="parameters"></param>
/// <returns></returns> /// <returns></returns>
public IEnumerable<TPluginRuntimeInfo> LoadPlugins(Assembly[] assemblies, params object?[]? parameters) public IEnumerable<PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo>> LoadPlugins(Assembly[] assemblies, params object?[]? parameters)
{ {
foreach (var assembly in assemblies) foreach (var assembly in assemblies)
yield return LoadPlugin(assembly, parameters); yield return LoadPlugin(assembly, parameters);
@@ -51,7 +51,7 @@ namespace Pilz.Plugins
/// </summary> /// </summary>
/// <param name="listenAssemblyLoadContext">Do also load plugins from all yet not loaded assemblies by listening the event <see cref="AppDomain.AssemblyLoad"/>. /// <param name="listenAssemblyLoadContext">Do also load plugins from all yet not loaded assemblies by listening the event <see cref="AppDomain.AssemblyLoad"/>.
/// <returns></returns> /// <returns></returns>
public IEnumerable<TPluginRuntimeInfo> LoadOwnPlugins(bool listenAssemblyLoadContext, params object?[]? parameters) public IEnumerable<PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo>> LoadOwnPlugins(bool listenAssemblyLoadContext, params object?[]? parameters)
{ {
if (listenAssemblyLoadContext) if (listenAssemblyLoadContext)
AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
@@ -66,29 +66,29 @@ namespace Pilz.Plugins
/// <param name="path"></param> /// <param name="path"></param>
/// <param name="parameters"></param> /// <param name="parameters"></param>
/// <returns></returns> /// <returns></returns>
public TPluginRuntimeInfo LoadPlugin(string path, params object?[]? parameters) public PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo> LoadPlugin(string path, params object?[]? parameters)
{ {
var info = Activator.CreateInstance<TPluginRuntimeInfo>(); var result = new PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo>();
var loadContext = new PluginLoadContext(path); var loadContext = new PluginLoadContext(path);
if (File.Exists(path)) if (File.Exists(path))
{ {
try try
{ {
info.Assembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path))); result.Assembly = loadContext.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(path)));
} }
catch catch
{ {
info.Status = PluginStatus.ErrorAtLoading; result.Status = PluginLoadStatus.ErrorAtLoading;
} }
} }
else else
info.Status = PluginStatus.FileNotFound; result.Status = PluginLoadStatus.FileNotFound;
if (info.Assembly != null) if (result.Assembly != null)
info = LoadPlugin(info.Assembly, parameters); LoadPlugin(result, parameters);
return info; return result;
} }
/// <summary> /// <summary>
@@ -97,28 +97,36 @@ namespace Pilz.Plugins
/// <param name="assembly"></param> /// <param name="assembly"></param>
/// <param name="parameters"></param> /// <param name="parameters"></param>
/// <returns></returns> /// <returns></returns>
public TPluginRuntimeInfo LoadPlugin(Assembly assembly, params object?[]? parameters) public PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo> LoadPlugin(Assembly assembly, params object?[]? parameters)
{ {
var info = Activator.CreateInstance<TPluginRuntimeInfo>(); var result = new PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo>
info.Assembly = assembly; {
LoadPlugin(info); Assembly = assembly
return info; };
LoadPlugin(result);
return result;
} }
private void LoadPlugin(TPluginRuntimeInfo info, params object?[]? parameters) private void LoadPlugin(PluginLoadInfo<TPluginInterface, TPluginRuntimeInfo> result, params object?[]? parameters)
{ {
var irmplugin = typeof(TPluginInterface); var irmplugin = typeof(TPluginInterface);
if (info.Assembly == null) if (result.Assembly == null)
info.Status = PluginStatus.NoValidPlugin; result.Status = PluginLoadStatus.NoValidPlugin;
else if (loadedPlugins.Any(n => n.Assembly == info.Assembly)) else if (loadedPlugins.Any(n => n.Assembly == result.Assembly))
info.Status = PluginStatus.AlreadyLoaded; result.Status = PluginLoadStatus.AlreadyLoaded;
else else
{ {
foreach (var type in info.Assembly.GetTypes()) foreach (var type in result.Assembly.GetTypes())
{ {
if (info.Plugin == null && irmplugin.IsAssignableFrom(type)) if (irmplugin.IsAssignableFrom(type))
{ {
var info = Activator.CreateInstance<TPluginRuntimeInfo>();
info.Assembly = result.Assembly;
result.PluginsInternal.Add(info);
try try
{ {
if (Activator.CreateInstance(type, parameters) is TPluginInterface plugin) if (Activator.CreateInstance(type, parameters) is TPluginInterface plugin)
@@ -136,8 +144,8 @@ namespace Pilz.Plugins
} }
} }
if (info.Plugin == null) if (result.PluginsInternal.Count == 0)
info.Status = PluginStatus.NoValidPlugin; result.Status = PluginLoadStatus.NoValidPlugin;
} }
} }
} }

View File

@@ -10,9 +10,6 @@ namespace Pilz.Plugins
{ {
None, None,
Success, Success,
AlreadyLoaded,
FileNotFound,
ErrorAtLoading,
ErrorAtInitializing, ErrorAtInitializing,
NoValidPlugin NoValidPlugin
} }