我知道一种重构安全的方法,可以使用此答案获取属性名称。 是否有一种重构安全的方式来获取方法的名称?
我正在使用 C# 5 和 .Net 4.5。
为了说明我正在尝试做什么:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
//I'd like to get the method names for UnitTestOne and UnitTestTwo here
//in such a way that this code will raise a compile time error if either
//the UnitTestOne or UnitTestTwo method names changes.
}
}
更新:这是一篇很好的文章,它解释并提供了一种灵活的实用工具方法,可以使用重构安全代码访问 MethodInfos。 http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
我认为 Jon Skeet 的答案很好,如果你只想涵盖 void 无参数方法。 更通用的解决方案如下所示:
public class MyClass
{
public void UnitTestOne(int i) { /* impl */ }
public int UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var methodCallExpressions = new Expression<Action<MyClass>>[] {
mc => mc.UnitTestOne(default(int)), //Note that a dummy argument is provided
mc => mc.UnitTestTwo()
};
var names = methodCallExpressions.Select(mce =>
((MethodCallExpression) mce.Body).Method.Name);
}
}
请注意,我们使用Expression<Action<MyClass>>
数组来列出MyClass
的方法调用,而不知道每个方法调用的返回类型和参数类型。 每个方法调用表达式都提供虚拟变量来实例化表达式。
然后,每个表达式的主体被强制转换为一个MethodCallExpression
,如类型名称所示,该包含的表达式只是对方法的调用。 该类型具有一个 Method
属性,该属性是所调用方法的MethodInfo
。
在您提供的链接中,使用 MemberExpression
类似地提取属性名称。 使用MethodCallExpression
使示例非常相似。
顺便说一句,如果您愿意,也可以使用Expression<Action>
而不是Expression<Action<MyClass>>
。 将methodCallExpressions
实例化替换为:
var methodCallExpressions = new Expression<Action>[] {
() => this.UnitTestOne(default(int)),
() => this.UnitTestTwo()
};
我认为这主要是一个风格决定,尽管它也允许您使用类似 () => (new MyClass2()).UnitTestThree()
的东西封装不同类的方法调用。
最简单的方法可能只是为每个方法创建一个委托,并使用 MulticastDelegate.Method
属性:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var actions = new Action[] { UnitTestOne, UnitTestTwo };
var names = actions.Select(x => x.Method.Name);
}
}