这里有一个类似的问题:
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次重载来发送垃圾邮件。
那么,我该怎么做?
答案 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(字符串)也是如此。