From abcd0e0d6cb5532c8a19a8cd8c7dd83e7f143442 Mon Sep 17 00:00:00 2001 From: vnugent Date: Wed, 11 Sep 2024 16:43:20 -0400 Subject: Managed library & package updates --- lib/Utils/src/Resources/ManagedLibrary.cs | 80 ++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) (limited to 'lib/Utils') 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 /// The optional method binind flags /// The delegate if found otherwise /// - public static TDelegate? TryGetStaticMethod(Type type, string methodName, BindingFlags flags = BindingFlags.Public) where TDelegate : Delegate + public static TDelegate? TryGetStaticMethod(Type type, string methodName, BindingFlags flags = BindingFlags.Public) + where TDelegate : Delegate => TryGetMethodInternal(type, methodName, null, flags | BindingFlags.Static); /// @@ -276,7 +277,8 @@ namespace VNLib.Utils.Resources /// The optional method binind flags /// The delegate if found otherwise /// - public static TDelegate? TryGetStaticMethod(string methodName,BindingFlags flags = BindingFlags.Public) where TDelegate : Delegate + public static TDelegate? TryGetStaticMethod(string methodName,BindingFlags flags = BindingFlags.Public) + where TDelegate : Delegate => TryGetMethodInternal(typeof(TType), methodName, null, flags | BindingFlags.Static); private static TDelegate? TryGetMethodInternal(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(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 + */ + + /// + /// 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. + /// + /// The function attribute type + /// The function delegate type + /// The object instance to get the method delegates for + /// The method binding flags to search for + /// An array of function with the desired attribute assigned, an empty array if no methods are found + public static TFunc[] GetMethodsWithAttribute(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(obj)) + .ToArray(); + } + + /// + /// 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. + /// + /// The function attribute type + /// The function delegate type + /// Type of the static class to get methods for + /// The method binding flags to search for + /// An array of function with the desired attribute assigned, an empty array if no methods are found + public static TFunc[] GetStaticMethodsWithAttribute(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(null)) + .ToArray(); + } } } -- cgit