comments & fixes

This commit is contained in:
2024-05-02 08:23:01 +02:00
parent d56d1d1851
commit bda33e1c8a

View File

@@ -7,10 +7,14 @@ using System.Threading.Tasks;
namespace Pilz.Plugins.Advanced namespace Pilz.Plugins.Advanced
{ {
public sealed class PluginFeatureController public class PluginFeatureController
{ {
// D e l e g a t e s
public delegate void PluginFeatureEventHandler(PluginFeatureController controller, PluginFeature feature); public delegate void PluginFeatureEventHandler(PluginFeatureController controller, PluginFeature feature);
// S t a t i c E v e n t s
/// <summary> /// <summary>
/// Fires when a new <see cref="PluginFeature"/> has been registred. /// Fires when a new <see cref="PluginFeature"/> has been registred.
/// </summary> /// </summary>
@@ -21,11 +25,20 @@ namespace Pilz.Plugins.Advanced
/// </summary> /// </summary>
public static event PluginFeatureEventHandler? OnPluginFeatureUnregistred; 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)}";
/// <summary> /// <summary>
/// The default public instance that can be used by plugins and the interface providing software. /// The default public instance that can be used by plugins and the interface providing software.
/// </summary> /// </summary>
public static PluginFeatureController Instance { get; private set; } = new(); 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<PluginFeature> features = []; private readonly HashSet<PluginFeature> features = [];
/// <summary> /// <summary>
@@ -50,53 +63,96 @@ namespace Pilz.Plugins.Advanced
Modules = new(this); Modules = new(this);
} }
public void RegisterAllFromMyAssembly() /// <summary>
/// Registers all features found in the currently executing Assembly via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
public void RegisterAllOwn()
{ {
RegisterAllFromAssembly(Assembly.GetCallingAssembly()); RegisterAll(Assembly.GetCallingAssembly());
} }
public void RegisterAllFromAssembly(Assembly assembly) /// <summary>
/// Registers all features found in the given <see cref="Assembly[]"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="assemblies"></param>
public void RegisterAll(Assembly[] assemblies)
{ {
const string nameGetFeatures = $"{nameof(IPluginFeaturesProvider.GetFeatures)}"; foreach (var assembly in assemblies)
const string nameGetFeaturesExplicit = $"{nameof(IPluginFeaturesProvider)}.{nameof(IPluginFeaturesProvider.GetFeatures)}"; RegisterAll(assembly);
const string nameInstance = $"get_{nameof(IPluginFeatureProvider.Instance)}"; }
const string nameInstnaceExplicit = $"get_{nameof(IPluginFeatureProvider)}.{nameof(IPluginFeatureProvider.Instance)}";
foreach (var type in assembly.GetTypes()) /// <summary>
/// Registers all features found in the given <see cref="Assembly"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="assembly"></param>
public void RegisterAll(Assembly assembly)
{
RegisterAll(assembly.GetTypes());
}
/// <summary>
/// Registers all features found from the given <see cref="Type[]"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="types"></param>
public void RegisterAll(Type[] types)
{
foreach (var type in types)
RegisterAll(type);
}
/// <summary>
/// Registers all features found from the given <see cref="Type"/> via <see cref="IPluginFeatureProvider"/>, <see cref="IPluginFeatureProvider{T}"/> and <see cref="IPluginFeaturesProvider"/>.
/// <para><b>Note:</b><br/>Explicit implementations of <see cref="IPluginFeatureProvider{T}.Instance"/> can not be detected. For this case just implement <see cref="IPluginFeatureProvider.Instance"/> instead.</para>
/// </summary>
/// <param name="type"></param>
public void RegisterAll(Type type)
{
if (type.IsAssignableTo(typeof(IPluginFeaturesProvider)))
{ {
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);
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) 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); foreach (var feature in features)
var method = methods.FirstOrDefault(n => n.Name == nameInstnaceExplicit || n.Name == nameInstance);
if (method != null && method.Invoke(null, null) is PluginFeature feature)
Register(feature); 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);
}
} }
/// <summary>
/// Registers a feature via the given <see cref="IPluginFeatureProvider"/> or <see cref="IPluginFeatureProvider{T}"/>.
/// </summary>
public void Register<TProvider>() where TProvider : IPluginFeatureProvider public void Register<TProvider>() where TProvider : IPluginFeatureProvider
{ {
Register(TProvider.Instance); Register(TProvider.Instance);
} }
/// <summary>
/// Registers all features via the given <see cref="IPluginFeaturesProvider"/>.
/// </summary>
public void RegisterAll<TProvider>() where TProvider : IPluginFeaturesProvider public void RegisterAll<TProvider>() where TProvider : IPluginFeaturesProvider
{ {
foreach (var feature in TProvider.GetFeatures()) foreach (var feature in TProvider.GetFeatures())
Register(feature); Register(feature);
} }
/// <summary>
/// Registers the given feature.
/// </summary>
/// <param name="module"></param>
public void Register(PluginFeature module) public void Register(PluginFeature module)
{ {
if (!features.Contains(module)) if (!features.Contains(module))
@@ -106,6 +162,10 @@ namespace Pilz.Plugins.Advanced
} }
} }
/// <summary>
/// Unregisters the given feature.
/// </summary>
/// <param name="module"></param>
public void Unregister(PluginFeature module) public void Unregister(PluginFeature module)
{ {
features.Remove(module); features.Remove(module);