在C#中传递未知参数/返回类型作为参数的方法

时间:2013-01-14 18:16:57

标签: c# reflection linq-expressions methodinfo

这里有一个类似的问题:

Pass Method as Parameter using C#

假设您知道方法的参数和返回类型。我想做一些与众不同的事情。我正在寻找创建一个版本的System.Reflection的.GetMethod(字符串)而不是一个lambda函数 - 所以而不是:

MethodInfo methodInfo = typeof(MyClass).GetMethod("AddThing");

我可以使用更安全的编译:

MethodInfo methodInfo = ReflectionHelper.GetMethod<MyClass>(mc => mc.AddThing);

因此,如果ReflectionHelper事先知道参数count和返回类型,那么答案就是简单的 - 例如,如果它没有参数并且返回了字符串:

public static MethodInfo GetMethod<T, TReturn>(Expression<Func<T, Func<TArg, TReturn>>> expr)
{
    return ((MethodCallExpression)expr.Body).Method;
}

除非事先我不知道参数计数/返回类型,否则我想避免仅通过覆盖大多数但不是所有情况的20次重载来发送垃圾邮件。

那么,我该怎么做?

2 个答案:

答案 0 :(得分:3)

您尚未在lambda mc => mc.AddThing中指定方法 - 您已指定方法组。

你可以做的是在表达式中编写一个方法调用 - 尽管它永远不会被执行,所以参数只需要指定你想要的重载。

所以,要使用它,你会写:

MethodInfo mi = GetMethod<MyClass>( mc => mc.AddThing( null ) );

然后表达式可能只是Action,而不是Func

public static MethodInfo<T>( Expression<Action<T>> expr )
{
  return ( ( MethodCallExpression ) x.Body ).Method;
}

与表达式检查一样,如果lambda不是预期的形式,这很容易出现运行时错误,但这是朝着正确方向摆脱“魔术”字符串的一步。

答案 1 :(得分:0)

我现在正在使用的解决方法,我称之为“垃圾邮件方法”,在一组有限的场景中很难看但功能正常:

public class ReflectionHelper<T>
{
    public MethodInfo GetMethod<TA1>(Expression<Func<T, Func<TA1>>> expr)
    {
        return ((MethodCallExpression)expr.Body).Method;
    }
    public MethodInfo GetMethod<TA1, TA2>(Expression<Func<T, Action<TA1, TA2>>> expr)
    {
        return ((MethodCallExpression)expr.Body).Method;
    }
    public MethodInfo GetMethod<TA1, TA2, TA3>(Expression<Func<T, Action<TA1, TA2, TA3>>> expr)
    {
        return ((MethodCallExpression)expr.Body).Method;
    }
    . . . // And more
}

接下来,指定一个包含各种参数计数的潜在动作和Func的长列表。这使我实际上可以使用它:

(new ReflectionHelper<MyClass>()).GetMethod<string>(mc => mc.SaySomething).Invoke("Hi");

所以它是关闭的 - 我只是按名称调用方法,并且我确实避免传递假参数以便这样做,但我仍然可以找到它的参数的类型 - 更复杂比我希望的那样。在具有相同名称的多个方法重载的情况下,传递参数类型会将方法列表缩小到一个特定的重载。

我仍然对一些更简单的东西感兴趣,但是可以采用我的问题中的方法。在方法过载情况下它会很模糊,但标准.GetMethod(字符串)也是如此。