如何将特定签名的任意委托转换为Func<MyClass, object[], bool>?
Func<MyClass, object[], bool>? Absolutely, this is totally feasible! The core idea is to wrap your existing delegates in a lambda (or build a dynamic wrapper via expression trees) that takes the MyClass instance and an object[] of arguments, then unpacks and converts those arguments to match the original delegate's parameter types before invoking it.
Manual Adapter Example
For each of your specific methods, you can create a direct Func<MyClass, object[], bool> wrapper explicitly:
First, let's define our example types and methods:
public class MyClass { } public class AnotherClass { } public static bool FirstMethod(MyClass foo, int integer, string text) { return integer > 0 && !string.IsNullOrEmpty(text); } public static bool SecondMethod(MyClass foo, string text, AnotherClass bar) { return text != null && bar != null; }
Now wrap them into the desired Func type:
// Wrap FirstMethod Func<MyClass, object[], bool> firstFunc = (myObj, args) => FirstMethod(myObj, (int)args[0], (string)args[1]); // Wrap SecondMethod Func<MyClass, object[], bool> secondFunc = (myObj, args) => SecondMethod(myObj, (string)args[0], (AnotherClass)args[1]);
You can then call these wrappers like so:
var myInstance = new MyClass(); bool firstResult = firstFunc(myInstance, new object[] { 42, "Stack Overflow" }); bool secondResult = secondFunc(myInstance, new object[] { "Hello", new AnotherClass() });
Generic Reusable Solution
If you have many such delegates and don't want to write manual wrappers for each, you can use expression trees to build a generic converter. This automatically handles the argument unpacking and type conversion:
public static Func<MyClass, object[], bool> ConvertToTargetDelegate<TDelegate>(TDelegate del) where TDelegate : Delegate { var method = del.Method; // Validate the delegate meets our requirements if (method.ReturnType != typeof(bool)) throw new ArgumentException("Delegate must return a boolean value."); var parameters = method.GetParameters(); if (parameters.Length == 0 || parameters[0].ParameterType != typeof(MyClass)) throw new ArgumentException("Delegate's first parameter must be of type MyClass."); // Build expression tree nodes for the Func parameters var myClassParam = Expression.Parameter(typeof(MyClass), "myObj"); var argsParam = Expression.Parameter(typeof(object[]), "args"); // Build the list of arguments for the original method call var callArguments = new List<Expression> { myClassParam }; for (int i = 1; i < parameters.Length; i++) { var targetType = parameters[i].ParameterType; // Get the argument from the object array and convert it to the target type var argIndex = Expression.Constant(i - 1); var argExpr = Expression.ArrayIndex(argsParam, argIndex); var convertedArg = Expression.Convert(argExpr, targetType); callArguments.Add(convertedArg); } // Create the method call expression var methodCall = Expression.Call(Expression.Constant(del.Target), method, callArguments); // Compile the expression into a Func var lambda = Expression.Lambda<Func<MyClass, object[], bool>>(methodCall, myClassParam, argsParam); return lambda.Compile(); }
Using this generic converter is straightforward:
// Convert FirstMethod var firstGenericFunc = ConvertToTargetDelegate((Func<MyClass, int, string, bool>)FirstMethod); // Convert SecondMethod var secondGenericFunc = ConvertToTargetDelegate((Func<MyClass, string, AnotherClass, bool>)SecondMethod); // Call them just like the manual wrappers bool genericFirstResult = firstGenericFunc(myInstance, new object[] { 10, "Test" }); bool genericSecondResult = secondGenericFunc(myInstance, new object[] { "Example", new AnotherClass() });
Key Notes
- When calling the wrapped
Func, ensure theobject[]contains exactly the right number of arguments in the correct order, and that each argument can be converted to the original parameter type (e.g., don't pass a string where an int is expected—this will throw a cast exception). - For instance methods, make sure the target object (the instance the delegate is bound to) remains valid for the lifetime of the wrapped
Func. - The expression tree approach incurs a one-time compilation cost, but is much more scalable if you have many delegates to convert.
内容的提问来源于stack exchange,提问作者Chilli

