using Microsoft.VisualBasic;
using System.Reflection;
namespace Pilz.Plugins.Advanced;
public class PluginFeatureController
{
// D e l e g a t e s
public delegate void PluginFeatureEventHandler(PluginFeatureController controller, PluginFeature feature);
// S t a t i c E v e n t s
///
/// Fires when a new has been registred.
///
public static event PluginFeatureEventHandler? OnPluginFeatureReistred;
///
/// Fires when a has been unregistred.
///
public static event PluginFeatureEventHandler? OnPluginFeatureUnregistred;
// S t a t i c M e m b e r s
protected static readonly string nameGetFeatures = $"{nameof(IPluginFeaturesProvider.GetFeatures)}";
protected static readonly string nameGetFeaturesExplicit = $"{typeof(IPluginFeaturesProvider).FullName}.{nameof(IPluginFeaturesProvider.GetFeatures)}";
protected static readonly string nameInstance = $"get_{nameof(IPluginFeatureProvider.Instance)}";
protected static readonly string nameInstnaceExplicit = $"{typeof(IPluginFeaturesProvider).FullName}.get_{nameof(IPluginFeatureProvider.Instance)}";
///
/// The default public instance that can be used by plugins and the interface providing software.
///
public static PluginFeatureController Instance { get; private set; } = new();
// I n s t a n c e M e m e b e r s
private readonly HashSet features = [];
///
/// A wrapper of all registred instances.
///
public FeatureController Features { get; init; }
///
/// A wrapper for all registred instances.
///
public ModuleController Modules { get; init; }
///
/// A wrapper for all registred instances.
///
public FunctionController Functions { get; init; }
public PluginFeatureController()
{
Features = new(this);
Functions = new(this);
Modules = new(this);
}
///
/// Registers all features found in the currently executing Assembly via , and .
/// Note: Explicit implementations of can not be detected. For this case just implement instead.
///
public void RegisterAllOwn(string? @namespace = null)
{
RegisterAll(Assembly.GetCallingAssembly());
}
///
/// Registers all features found in the given via , and .
/// Note: Explicit implementations of can not be detected. For this case just implement instead.
///
/// The assemblies to query for types.
/// If not null, only types within the given namespace will be registered.
public void RegisterAll(Assembly[] assemblies, string? @namespace = null)
{
foreach (var assembly in assemblies)
RegisterAll(assembly);
}
///
/// Registers all features found in the given via , and .
/// Note: Explicit implementations of can not be detected. For this case just implement instead.
///
/// The assembly to query for types.
/// If not null, only types within the given namespace will be registered.
public void RegisterAll(Assembly assembly, string? @namespace = null)
{
RegisterAll(assembly.GetTypes());
}
///
/// Registers all features found from the given via , and .
/// Note: Explicit implementations of can not be detected. For this case just implement instead.
///
/// The types to query for providers.
/// If not null, the types will only be processed if they're within the given namespace.
public void RegisterAll(Type[] types, string? @namespace = null)
{
foreach (var type in types)
RegisterAll(type);
}
///
/// Registers all features found from the given via , and .
/// Note: Explicit implementations of can not be detected. For this case just implement instead.
///
/// The type to query for providers.
/// If not null, the type will only be processed if it's within the given namespace.
public void RegisterAll(Type type, string? @namespace = null)
{
if (@namespace != null && type.Namespace != null && type.Namespace != @namespace && !type.Namespace.StartsWith(@namespace + "."))
return;
if (type.IsAssignableTo(typeof(IPluginFeaturesProvider)))
{
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var method = methods.FirstOrDefault(n => n.Name == nameGetFeaturesExplicit || n.Name == nameGetFeatures);
if (method != null && method.Invoke(null, null) is PluginFeature[] features)
{
foreach (var feature in features)
Register(feature);
}
}
else if (type.IsAssignableTo(typeof(IPluginFeatureProvider)))
{
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var method = methods.FirstOrDefault(n => n.Name == nameInstnaceExplicit || n.Name == nameInstance);
if (method != null && method.Invoke(null, null) is PluginFeature feature)
Register(feature);
}
else if (type.IsAssignableTo(typeof(IPluginFeatureConstructor)))
{
if (type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, [typeof(PluginFeatureController)]) is ConstructorInfo ctor1)
{
if (ctor1.Invoke([this]) is PluginFeature feature)
Register(feature);
}
else if (type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, []) is ConstructorInfo ctor)
{
if (ctor.Invoke([]) is PluginFeature feature)
Register(feature);
}
}
}
///
/// Registers a feature via the given or .
///
public void Register() where TProvider : IPluginFeatureProvider
{
Register(TProvider.Instance);
}
///
/// Registers all features via the given .
///
public void RegisterAll() where TProvider : IPluginFeaturesProvider
{
foreach (var feature in TProvider.GetFeatures())
Register(feature);
}
///
/// Registers the given feature.
///
///
public void Register(PluginFeature module)
{
if (!features.Contains(module))
{
features.Add(module);
OnPluginFeatureReistred?.Invoke(this, module);
}
}
///
/// Unregisters the given feature.
///
///
public void Unregister(PluginFeature module)
{
features.Remove(module);
OnPluginFeatureUnregistred?.Invoke(this, module);
}
public class FeatureController(PluginFeatureController controller)
{
protected readonly PluginFeatureController controller = controller;
public virtual IEnumerable GetAll()
{
return controller.features.ToArray();
}
public virtual IEnumerable Get(string featureType)
{
return controller.features.Where(n => n.Type == featureType);
}
public virtual PluginFeature? GetFirst(string featureType)
{
return controller.features.FirstOrDefault(n => n.Type == featureType);
}
public virtual PluginFeature? GetByIdentifier(string fullIdentifier)
{
return controller.features.FirstOrDefault(n => n.FullIdentifier == fullIdentifier);
}
public virtual PluginFeature? GetByIdentifier(string featureType, string identifier)
{
return controller.features.FirstOrDefault(n => n.Type == featureType && n.Identifier == identifier);
}
}
public class FeatureController(PluginFeatureController controller) : FeatureController(controller) where T : PluginFeature
{
public override IEnumerable GetAll()
{
return controller.features.OfType();
}
public override IEnumerable Get(string moduleType)
{
return GetAll().Where(n => n.Type == moduleType);
}
public override T? GetFirst(string moduleType)
{
return base.GetFirst(moduleType) as T;
}
public override T? GetByIdentifier(string fullIdentifier)
{
return base.GetByIdentifier(fullIdentifier) as T;
}
public override T? GetByIdentifier(string featureType, string identifier)
{
return base.GetByIdentifier(featureType, identifier) as T;
}
}
public class ModuleController(PluginFeatureController controller) : FeatureController(controller)
{
}
public class FunctionController(PluginFeatureController controller) : FeatureController(controller)
{
public void ExecuteAll(string functionType)
{
foreach (var function in Get(functionType))
function.Execute();
}
public void ExecuteAll(string functionType, params object?[]? @params)
{
foreach (var function in Get(functionType))
function.Execute(@params);
}
public void ExecuteAll(string functionType, PluginFunctionParameter @params)
{
foreach (var function in Get(functionType))
function.Execute(@params);
}
public IEnumerable