繁体   English   中英

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

[英]How to create delegate of Func<a,b> when a's method has parameters

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

有指针吗? 我必须使用表达式树吗? 有没有更简单的方法可以做到这一点?

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

就像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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM