aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2024-09-11 16:43:20 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2024-09-11 16:43:20 -0400
commitabcd0e0d6cb5532c8a19a8cd8c7dd83e7f143442 (patch)
tree565c42a5b6951c3e1ca9925f99fd0c58c1ed498d
parent2ae018af277b808786cf398c689910bc016e7ef0 (diff)
Managed library & package updates
-rw-r--r--lib/Plugins.Runtime/src/LivePlugin.cs40
-rw-r--r--lib/Utils/src/Resources/ManagedLibrary.cs80
2 files changed, 89 insertions, 31 deletions
diff --git a/lib/Plugins.Runtime/src/LivePlugin.cs b/lib/Plugins.Runtime/src/LivePlugin.cs
index 3ed2ad6..26276dd 100644
--- a/lib/Plugins.Runtime/src/LivePlugin.cs
+++ b/lib/Plugins.Runtime/src/LivePlugin.cs
@@ -26,6 +26,7 @@ using System;
using System.Linq;
using System.Reflection;
+using VNLib.Utils.Resources;
using VNLib.Plugins.Attributes;
namespace VNLib.Plugins.Runtime
@@ -76,18 +77,14 @@ namespace VNLib.Plugins.Runtime
Plugin = plugin;
OriginAsm = originAsm;
PluginType = plugin.GetType();
- GetConsoleHandler();
+ PluginConsoleHandler = GetConsoleHandler(plugin);
}
- private void GetConsoleHandler()
+ private static ConsoleEventHandlerSignature? GetConsoleHandler(IPlugin plugin)
{
- //Get the console handler method from the plugin instance
- MethodInfo? handler = (from m in PluginType.GetMethods()
- where m.GetCustomAttribute<ConsoleEventHandlerAttribute>() != null
- select m)
- .FirstOrDefault();
//Get a delegate handler for the plugin
- PluginConsoleHandler = handler?.CreateDelegate<ConsoleEventHandlerSignature>(Plugin);
+ return ManagedLibrary.GetMethodsWithAttribute<ConsoleEventHandlerAttribute, ConsoleEventHandlerSignature>(plugin)
+ .FirstOrDefault();
}
/// <summary>
@@ -97,18 +94,9 @@ namespace VNLib.Plugins.Runtime
/// <param name="configData">The host configuration DOM</param>
internal void InitConfig(ReadOnlySpan<byte> configData)
{
- //Get the console handler method from the plugin instance
- MethodInfo? confHan = PluginType.GetMethods().Where(static m => m.GetCustomAttribute<ConfigurationInitalizerAttribute>() != null)
- .FirstOrDefault();
- //Get a delegate handler for the plugin
- ConfigInitializer? configInit = confHan?.CreateDelegate<ConfigInitializer>(Plugin);
- if (configInit == null)
- {
- return;
- }
-
- //Invoke
- configInit.Invoke(configData);
+ ManagedLibrary.GetMethodsWithAttribute<ConfigurationInitalizerAttribute, ConfigInitializer>(Plugin!)
+ .FirstOrDefault()
+ ?.Invoke(configData);
}
/// <summary>
@@ -118,15 +106,9 @@ namespace VNLib.Plugins.Runtime
/// <param name="cliArgs">The current process's CLI args</param>
internal void InitLog(string[] cliArgs)
{
- //Get the console handler method from the plugin instance
- MethodInfo? logInit = (from m in PluginType.GetMethods()
- where m.GetCustomAttribute<LogInitializerAttribute>() != null
- select m)
- .FirstOrDefault();
- //Get a delegate handler for the plugin
- LogInitializer? logFunc = logInit?.CreateDelegate<LogInitializer>(Plugin);
- //Invoke
- logFunc?.Invoke(cliArgs);
+ ManagedLibrary.GetMethodsWithAttribute<LogInitializerAttribute, LogInitializer>(Plugin!)
+ .FirstOrDefault()
+ ?.Invoke(cliArgs);
}
/// <summary>
diff --git a/lib/Utils/src/Resources/ManagedLibrary.cs b/lib/Utils/src/Resources/ManagedLibrary.cs
index c899156..5faaa19 100644
--- a/lib/Utils/src/Resources/ManagedLibrary.cs
+++ b/lib/Utils/src/Resources/ManagedLibrary.cs
@@ -263,7 +263,8 @@ namespace VNLib.Utils.Resources
/// <param name="flags">The optional method binind flags</param>
/// <returns>The delegate if found <see langword="null"/> otherwise</returns>
/// <exception cref="ArgumentNullException"></exception>
- public static TDelegate? TryGetStaticMethod<TDelegate>(Type type, string methodName, BindingFlags flags = BindingFlags.Public) where TDelegate : Delegate
+ public static TDelegate? TryGetStaticMethod<TDelegate>(Type type, string methodName, BindingFlags flags = BindingFlags.Public)
+ where TDelegate : Delegate
=> TryGetMethodInternal<TDelegate>(type, methodName, null, flags | BindingFlags.Static);
/// <summary>
@@ -276,7 +277,8 @@ namespace VNLib.Utils.Resources
/// <param name="flags">The optional method binind flags</param>
/// <returns>The delegate if found <see langword="null"/> otherwise</returns>
/// <exception cref="ArgumentNullException"></exception>
- public static TDelegate? TryGetStaticMethod<TDelegate, TType>(string methodName,BindingFlags flags = BindingFlags.Public) where TDelegate : Delegate
+ public static TDelegate? TryGetStaticMethod<TDelegate, TType>(string methodName,BindingFlags flags = BindingFlags.Public)
+ where TDelegate : Delegate
=> TryGetMethodInternal<TDelegate>(typeof(TType), methodName, null, flags | BindingFlags.Static);
private static TDelegate? TryGetMethodInternal<TDelegate>(Type type, string methodName, object? target, BindingFlags flags) where TDelegate : Delegate
@@ -293,5 +295,79 @@ namespace VNLib.Utils.Resources
return type.GetMethod(methodName, flags, delegateArgs)
?.CreateDelegate<TDelegate>(target);
}
+
+ /*
+ * NOTE: These functions cannot be optimized (condensed) any furhter. IE: static
+ * and instance method searches. This is because the C# compiler will embed the
+ * call to getType() of the object instead of loading reflection if possible
+ * at runtime. This can cause the type to be undefined at runtime and will not
+ * be able to find some members
+ */
+
+ /// <summary>
+ /// Gets an array of methods that have the specified attribute and match the
+ /// delegate signature of the desired type, and returns them as an array of delegates.
+ /// </summary>
+ /// <typeparam name="TAttr">The function attribute type</typeparam>
+ /// <typeparam name="TFunc">The function delegate type</typeparam>
+ /// <param name="obj">The object instance to get the method delegates for</param>
+ /// <param name="flags">The method binding flags to search for</param>
+ /// <returns>An array of function with the desired attribute assigned, an empty array if no methods are found</returns>
+ public static TFunc[] GetMethodsWithAttribute<TAttr, TFunc>(object obj, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
+ where TFunc : Delegate
+ where TAttr : Attribute
+ {
+ ArgumentNullException.ThrowIfNull(obj);
+
+ //Get the delegate type
+ Type funcType = typeof(TFunc);
+
+ //Get the delegate method signature
+ Type[] delegateArgs = funcType.GetMethod("Invoke")!
+ .GetParameters()
+ .Select(static p => p.ParameterType)
+ .ToArray();
+
+ //Get the method with the attribute that matches the same signature as the delegate
+ return obj.GetType()
+ .GetMethods(flags)
+ .Where(static m => m.GetCustomAttribute(typeof(TAttr)) != null)
+ .Where(m => m.GetParameters().Select(static p => p.ParameterType).SequenceEqual(delegateArgs))
+ .Select(method => method.CreateDelegate<TFunc>(obj))
+ .ToArray();
+ }
+
+ /// <summary>
+ /// Gets an array of static methods that have the specified attribute and match the
+ /// delegate signature of the desired type, and returns them as an array of delegates.
+ /// </summary>
+ /// <typeparam name="TAttr">The function attribute type</typeparam>
+ /// <typeparam name="TFunc">The function delegate type</typeparam>
+ /// <param name="classType">Type of the static class to get methods for</param>
+ /// <param name="flags">The method binding flags to search for</param>
+ /// <returns>An array of function with the desired attribute assigned, an empty array if no methods are found</returns>
+ public static TFunc[] GetStaticMethodsWithAttribute<TAttr, TFunc>(Type classType, BindingFlags flags = BindingFlags.Public | BindingFlags.Static)
+ where TFunc : Delegate
+ where TAttr : Attribute
+ {
+ ArgumentNullException.ThrowIfNull(classType);
+
+ //Get the delegate type
+ Type funcType = typeof(TFunc);
+
+ //Get the delegate method signature
+ Type[] delegateArgs = funcType.GetMethod("Invoke")!
+ .GetParameters()
+ .Select(static p => p.ParameterType)
+ .ToArray();
+
+ //Get the method with the attribute that matches the same signature as the delegate
+ return classType.GetType()
+ .GetMethods(flags)
+ .Where(static m => m.GetCustomAttribute(typeof(TAttr)) != null)
+ .Where(m => m.GetParameters().Select(static p => p.ParameterType).SequenceEqual(delegateArgs))
+ .Select(method => method.CreateDelegate<TFunc>(null))
+ .ToArray();
+ }
}
}