当 a 的方法有参数时,如何创建 Func<a,b> 的委托



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

指针吗?我必须使用表达式树吗?有更简单的方法吗?

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());
    }
}

Like type.InvokeMember(method_name, System.Reflection.BindingFlags.InvokeMethod, null, type_instance, new object[] { param1, param2, param3 }); ?

https://msdn.microsoft.com/en-us/library/66btctbe (v = vs.110) . aspx

实际上整个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 ...
}

如果您需要MethodCaller.Do,但是可以牺牲签名类型(或者DoTyped的装箱/拆箱性能)

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());
    }
}

你试过看一下即兴框架吗?它主要用于鸭子类型,但库提供了相当灵活的api来访问方法和传递参数。

https://github.com/ekonbenefits/impromptu-interface/wiki/UsageReallyLateBinding

相关内容

最新更新