我希望能够将方法链接到所有类型的委托。我正在尝试使用refelection.emit
执行此操作并将动态方法与delagate的足迹相关联,将其添加到委托中,并让此动态方法调用包含所有参数的常规函数。但我希望有一个更简单的方法来做到这一点。
(我没有提供reflection.emit
代码,因为这不是我想要的帮助,这仍然是一个原始的尝试)
这是我想得到的结果示例:
public class FooClass
{
public delegate string MyFirstDelegate(string input1, string input2);
public delegate int MySecondDelegate(int input1, string input2, short input3);
public static MyFirstDelegate firstDelegate = null;
public static MySecondDelegate SecondDelegate = null;
private static string FirstMethod(string input1, string input2)
{
return input1 + input2;
}
private static int SecondMethod(int input1, string input2, short input3)
{
return input1 + Convert.ToInt32(input2) + input3;
}
private static object ThirdMethod(params object[] inputs)
{
//do some magic and return result
}
public static void Main()
{
firstDelegate = FirstMethod;
SecondDelegate = SecondMethod;
string result = firstDelegate("1", "2");
int result2 = SecondDelegate(1, "3", 3);
//obviously this does not work, but is there a way to link this method to the delegate?
firstDelegate = ThirdMethod;
SecondDelegate = ThirdMethod;
string result3 = firstDelegate("1", "2");
int result4 = SecondDelegate(1, "3", 3);
}
}
答案 0 :(得分:0)
要将方法链接到所有类型的委托,您可以使用Expression
制作帮助方法,如下所示:
private static TTarget ConvertDelegate<TTarget>(MethodInfo source)
{
var targetMethod = typeof(TTarget).GetMethod("Invoke");
var parameters = targetMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
var methodCall = Expression.Call(source, Expression.NewArrayInit(typeof(object), parameters));
var delegateExpression = Expression.Lambda<TTarget>(Expression.TypeAs(methodCall, targetMethod.ReturnType), parameters);
return delegateExpression.Compile();
}
然后你可以像这样使用它:
var methodInfo= typeof(FooClass).GetMethod(nameof(ThirdMethod), BindingFlags.NonPublic | BindingFlags.Static);
firstDelegate = ConvertDelegate<MyFirstDelegate>(methodInfo);
我还创建了帮助方法,从方法名称中获取MethodInfo
:
private static MethodInfo GetMethodInfo<T>(string methodName)
{
return typeof(T).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static);
}
private static TTarget ConvertDelegate<TTarget, TSource>(string sourceMethodName)
{
return ConvertDelegate<TTarget>(GetMethodInfo<TSource>(sourceMethodName));
}
然后你可以像这样使用它:
firstDelegate = ConvertDelegate<MyFirstDelegate, FooClass>(nameof(ThirdMethod));
不要忘记ConvertDelegate
只会使用签名object Name(object[] inputs)
包装方法,如果只需要包装一种方法,则可以将MethodInfo
保存在某个本地值中并且不要#39;每次都作为参数传递。