4

这里有一个类似的问题:

使用 C# 将方法作为参数传递

假设您知道方法的参数和返回类型。我想做点不一样的。我正在寻找创建 System.Reflection 的 .GetMethod(string) 的一个版本,它采用 lambda 函数 - 所以而不是:

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

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

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

因此,如果 ReflectionHelper 事先知道参数计数和返回类型,那么答案将很简单——例如,如果它没有参数并返回字符串:

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

除了我事先不知道参数计数/返回类型,我想避免只是用 20 个覆盖大多数但不是所有情况的重载来发送垃圾邮件。

那么,我该怎么做呢?

4

2 回答 2

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 不是预期的形式,这很容易出现运行时错误,但这是朝着摆脱“神奇”字符串的正确方向迈出的一步。

于 2013-01-14T18:34:50.977 回答
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
}

它继续,指定一长串具有各种参数计数的潜在动作和函数。这使我实际上可以像这样使用它:

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

所以它很接近 - 我只需按名称调用该方法,并且我确实避免传递虚假参数以便这样做,但我仍然被困在列出其参数的类型是什么 - 比我希望的要复杂为了。但是,在具有多个同名方法重载的情况下,传递参数的类型会将方法列表缩小到一个特定的重载。

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

于 2013-01-15T10:24:43.453 回答