C# 如何创建函数的委托<;a、 b>;当a';s方法有参数

C# 如何创建函数的委托<;a、 b>;当a';s方法有参数,c#,function,reflection,delegates,C#,Function,Reflection,Delegates,我试图调用一个接受函数的方法,但使用relation。我已经让它在方法无参数时工作,但我不知道在有参数时如何调用它。这是一个人为简化的例子,但这可以归结为问题。直到运行时,我才知道要添加的参数 有什么建议吗?我必须使用表达式树吗?有没有更简单的方法 public void Main() { //works CallFunction(typeof (Processor), "Count"); //I don't understand what I need to modif

我试图调用一个接受函数的方法,但使用relation。我已经让它在方法无参数时工作,但我不知道在有参数时如何调用它。这是一个人为简化的例子,但这可以归结为问题。直到运行时,我才知道要添加的参数

有什么建议吗?我必须使用表达式树吗?有没有更简单的方法

public void Main()
{
    //works
    CallFunction(typeof (Processor), "Count");
    //I don't understand what I need to modify to make add work
    CallFunction(typeof (Processor), "Add");
}

public void CallFunction(Type type, string methodToCall)
{
    var targetMethod = type.GetMethod(methodToCall);
    var constructedType = typeof (MethodCaller<>).MakeGenericType(type);
    dynamic target = Activator.CreateInstance(constructedType);
    var method = constructedType.GetMethod("Do").MakeGenericMethod(targetMethod.ReturnType);
    var func =  typeof (Func<,>).MakeGenericType(type, targetMethod.ReturnType);
    var toCall = Delegate.CreateDelegate(func, targetMethod);
    method.Invoke(target, new object[] { toCall });
}

public class Processor
{
    public int Count()
    {
        return 1;
    }
    public int Add(int toAdd)
    {
        return 1 + toAdd;
    }
}

public class MethodCaller<TParm> where TParm : new()
{
    public TResult Do<TResult>(Func<TParm, TResult> func)
    {
        return func(new TParm());
    }
}
public void Main()
{
//工作
调用函数(类型(处理器),“计数”);
//我不明白我需要修改什么才能使add工作
调用函数(类型(处理器),“添加”);
}
公共void调用函数(类型,字符串方法调用)
{
var targetMethod=type.GetMethod(methodToCall);
var constructedType=typeof(MethodCaller);
动态目标=Activator.CreateInstance(constructedType);
var method=constructedType.GetMethod(“Do”).MakeGenericMethod(targetMethod.ReturnType);
var func=typeof(func).MakeGenericType(type,targetMethod.ReturnType);
var toCall=Delegate.CreateDelegate(func,targetMethod);
调用(目标,新对象[]{toCall});
}
公共类处理器
{
公共整数计数()
{
返回1;
}
公共整数添加(整数添加)
{
返回1+toAdd;
}
}
公共类MethodCaller,其中TParm:new()
{
公共TResult Do(Func Func)
{
返回函数(新的TParm());
}
}

您是否尝试过查看即兴框架。它主要用于duck类型,但库提供了相当灵活的api来访问方法和传递参数


类似
type.InvokeMember(方法\u名称,System.Reflection.BindingFlags.InvokeMethod,null,类型\u实例,新对象[]{param1,param2,param3})

实际上整个
CallFunction
方法可以简化如下:

public void CallFunction(Type type, string methodToCall, params object[] args)
{
    // Why this part is so complex? Do I miss something?
    //var constructedType = typeof (MethodCaller<>).MakeGenericType(type);
    //dynamic target = Activator.CreateInstance(constructedType);

    var target = Activator.CreateInstance(type);
    var result = type.InvokeMember(method_name, System.Reflection.BindingFlags.InvokeMethod, null, target, args);
    // ... do something with result if you need ...
}

您需要一个适当版本的Func(具有适当数量的泛型参数),并了解这些参数的类型。代码的其余部分可以大致保持不变。无表情树necessary@KrzysztofKozmic如果我不知道Add有多少个参数,我怎么能指定Func。另外,处理器是否有一个方法Multiply(int x,int y)它实际上并没有改变Do的参数数量,它只接受处理器的一个函数?那么您打算如何调用它?我会在运行时知道参数的数量及其值,但typeof(func)是一个编译时常量eah。在这种情况下,您可能需要大量的if或字典来进行映射,这将在这个非常简单的示例中起作用,但是想象一下,如果我的do方法正在做一些更有趣的事情,并且我需要调用它,那么我已经找到了我缺少的东西。事实上,这是一个非常有趣的问题,在大量的家庭作业中:)这并不是我所问问题的答案,但它确实有效!我甚至没有想过不尝试在反射的代码中键入,而只是向MethodCaller添加一个helper方法。最终,我在这里实际要完成的基本任务是创建一个受支持的wcftestclient。MyMethodCaller包含创建通道和端点的逻辑。
public void CallFunction(Type type, string methodToCall, params object[] args)
{
    var delegate_wrapper = new Func<object, object>(
        instance => type.InvokeMember(methodToCall, BindingFlags.InvokeMethod, null, instance, args)
        );
    var target_method = type.GetMethod(methodToCall);

    var mc_custom_type = typeof (MethodCaller<>).MakeGenericType(type);
    var mc_instance = Activator.CreateInstance(mc_custom_type);
    var mc_custom_method = mc_custom_type.GetMethod("Do").MakeGenericMethod(target_method.ReturnType);

    mc_custom_method.Invoke(mc_instance, new object[] { delegate_wrapper });
}

public class MethodCaller<TParm> where TParm : new()
{
    public TResult DoTyped<TResult>(Func<TParm, TResult> func)
    {
        return Do<TResult>(oinstance=>func((TParm)oinstance));
    }

    public TResult Do<TResult>(Func<object, object> func)
    {
        Console.WriteLine("I AM DO");
        return (TResult)func(new TParm());
    }
}