152 lines
5.5 KiB
C#
152 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using global::System.Reflection;
|
|
using global::Pilz.Reflection.PluginSystem.Attributes;
|
|
|
|
namespace Pilz.Reflection.PluginSystem
|
|
{
|
|
public class Plugin
|
|
{
|
|
|
|
/// <summary>
|
|
/// A collection of Methods that contains PluginFunctions that will be called automatically when loading the Plugin, as long as the property AutoCallMainFunctions is set to True.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public IReadOnlyList<PluginFunction> MainFunctions { get; private set; }
|
|
/// <summary>
|
|
/// A collection of Methods with a FunctionCode (excluding all PluginFunctions from MainFunctions).
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public IReadOnlyList<PluginFunction> PluginFunctions { get; private set; }
|
|
/// <summary>
|
|
/// Gets the assembly that contains the PluginFunctions of this Plugin
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Assembly Assembly { get; private set; }
|
|
/// <summary>
|
|
/// Gets the main module that contains the PluginFunctions of this Plugin
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Type MainModule { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Load a new Plugin and its PluginFunctions.
|
|
/// </summary>
|
|
/// <param name="filePath"></param>
|
|
/// <param name="autoCallMainFunction">If true, all MainMethods of a Plugin will be called as soon as a Plugin is loaded.</param>
|
|
/// <param name="entryTypeName">The name of the type where to search for Methods when loading a new Plugin.</param>
|
|
public Plugin(string filePath, bool autoCallMainFunction, string entryTypeName)
|
|
{
|
|
Assembly = Assembly.LoadFile(filePath);
|
|
MainModule = Assembly.GetType(entryTypeName);
|
|
if (MainModule is null)
|
|
{
|
|
throw new PluginLoadException("Plugin Modul not found!");
|
|
}
|
|
|
|
// Define the attribute types to observe
|
|
var entryMethodType = typeof(LoadMethodAttribute);
|
|
var implementMethodType = typeof(PluginFunctionAttribute);
|
|
|
|
// Create the lists
|
|
var mainMethods = new List<PluginFunction>();
|
|
var implementMethods = new List<PluginFunction>();
|
|
|
|
// Search for PluginFunctions
|
|
foreach (MethodInfo mi in MainModule.GetMethods())
|
|
{
|
|
bool found = false;
|
|
|
|
// Check if the method has one of the defined attributes
|
|
foreach (Attribute attr in Attribute.GetCustomAttributes(mi))
|
|
{
|
|
if (!found)
|
|
{
|
|
var t = attr.GetType();
|
|
switch (t)
|
|
{
|
|
case var @case when @case == entryMethodType:
|
|
{
|
|
mainMethods.Add(new PluginFunction(mi, this));
|
|
break;
|
|
}
|
|
|
|
case var case1 when case1 == implementMethodType:
|
|
{
|
|
{
|
|
var withBlock = (PluginFunctionAttribute)attr;
|
|
implementMethods.Add(new PluginFunction(mi, this, withBlock.Params, withBlock.FunctionCode));
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the collections
|
|
MainFunctions = mainMethods;
|
|
PluginFunctions = implementMethods;
|
|
|
|
// Call all PluginFunctions in MainFunctions
|
|
if (autoCallMainFunction)
|
|
{
|
|
foreach (PluginFunction func in mainMethods)
|
|
{
|
|
var @params = func.Method.GetParameters();
|
|
if (@params.Length == 1)
|
|
{
|
|
string startupExe = Assembly.GetEntryAssembly().Location;
|
|
var args = new[] { startupExe, filePath };
|
|
func.Invoke(new[] { args });
|
|
}
|
|
else if (!@params.Any())
|
|
{
|
|
func.Invoke();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all PluginFunctions that have one of the given function codes.
|
|
/// </summary>
|
|
/// <param name="funcCodes"></param>
|
|
/// <returns></returns>
|
|
public IEnumerable<PluginFunction> GetFunctions(params string[] funcCodes)
|
|
{
|
|
var funcs = new List<PluginFunction>();
|
|
foreach (PluginFunction func in PluginFunctions)
|
|
{
|
|
if (funcCodes.Contains(func.FunctionCode))
|
|
{
|
|
funcs.Add(func);
|
|
}
|
|
}
|
|
|
|
return funcs;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the first PluginFunction that have the one of the given function codes.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public PluginFunction GetFunction(params string[] funcCodes)
|
|
{
|
|
PluginFunction f = null;
|
|
foreach (PluginFunction func in PluginFunctions)
|
|
{
|
|
if (f is null && funcCodes.Contains(func.FunctionCode))
|
|
{
|
|
f = func;
|
|
}
|
|
}
|
|
|
|
return f;
|
|
}
|
|
}
|
|
} |