>我有一个看起来像这样的成员MyClass.SpecialMethod()
我需要将此方法的名称作为字符串发送到另一个方法。我知道我可以使用TypeOf.GetMethods(..).Name
但是..将被硬编码,如果 SpecialMethod 更改名称,就会出现问题。
所以我想做的是这样的
TypeOf(MyClass).GetMethod(MyClass.SpecialMethod).Name
这是可能的,如果是这样,如何?
我知道我可以从方法内部获取当前方法的名称,但此时已经晚了。
能按照Jason的建议使用nameof()
,那就去做吧。
如果不这样做,请编写此帮助程序方法:
class MyClass {
public void SpecialMethod() {
var myName = WhatIsMyName();
}
private static string WhatIsMyName([CallerMemberName] string name= "") {
return name;
}
}
有关详细信息,请参阅 MSDN。请注意,如果调用方方法重载,您将获得它的名称,但它是不明确的。
它在较旧的 C# 版本中不受支持(已在 .NET 4.5 中引入)。如果您必须处理它们,那么您可能需要使用堆栈行走的老技巧来检查成员名称,大致如下所示:
[MethodImpl(MethodImplOptions.NoInlining)]
private static string WhatIsMyName() {
return new StackTrace().GetFrame(1).GetMethod().Name;
}
(注意[MethodImpl(MethodImplOptions.NoInlining)]
以防止内联,否则如果此调用是内联的,您将跳过(GetFrame(1)
而不是GetFrame(0)
请注意,所有这些技术(堆栈遍历、调用方信息、表达式)实际上都需要显式调用另一个方法,其中nameof()
在编译时解析。这可能是性能上的巨大差异(以防万一)。
C# 6.0,则可以使用新的"nameof"关键字
nameof(MyClass.SpecialMethod)
查看此处以获取更多信息("表达式名称"部分)
https://msdn.microsoft.com/en-us/magazine/dn802602.aspx
编辑:
文章中的示例用例:
namespace CSharp6.Tests
{
[TestClass]
public class NameofTests
{
[TestMethod]
public void Nameof_ExtractsName()
{
Assert.AreEqual<string>("NameofTests", nameof(NameofTests));
Assert.AreEqual<string>("TestMethodAttribute",
nameof(TestMethodAttribute));
Assert.AreEqual<string>("TestMethodAttribute",
nameof(
Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute));
Assert.AreEqual<string>("Nameof_ExtractsName",
string.Format("{0}", nameof(Nameof_ExtractsName)));
Assert.AreEqual<string>("Nameof_ExtractsName",
string.Format("{0}", nameof(
CSharp6.Tests.NameofTests.Nameof_ExtractsName)));
}
}
}
有Expression
的方法:
public static string GetName<TResult>(Expression<Func<TResult>> exp)
{
return GetName(exp != null ? exp.Body as MethodCallExpression : null);
}
public static string GetName(Expression<Action> exp)
{
return GetName(exp != null ? exp.Body as MethodCallExpression : null);
}
private static string GetName(MethodCallExpression mce)
{
if (mce == null)
{
throw new ArgumentNullException();
}
return mce.Method.Name;
}
请注意,它很慢...
像这样使用它:
string name = GetName(() => MyClass.SpecialMethod());
或者,如果该方法具有某些参数,请放置一些类型正确的值。该方法未执行,因此不是问题:
string name = GetName(() => MyClass.SpecialMethod(null, 5, default(DateTime)));
C# 6 名称非常整洁。
现在,可以在 .NET 4.5 中使用 CallerMemberName 属性,但如果无法使用该属性,或者名称不是来自调用方,则可以从表达式中提取名称。有人已经为此制作了一个实用程序。以下是他的代码。它使代码重构友好。
工作原理:
//Should return "Length", value type property
StaticReflection.GetMemberName<string>(x => x.Length);
//Should return "Data", reference type property
StaticReflection.GetMemberName<Exception>(x => x.Data);
//Should return "Clone", method returning reference type
StaticReflection.GetMemberName<string>(x => x.Clone());
//Should return "GetHashCode", method returning value type
StaticReflection.GetMemberName<string>(x => x.GetHashCode());
//Should return "Reverse", void method
StaticReflection.GetMemberName<List<string>>(x => x.Reverse());
//Should return "LastIndexOf", method with parameter
StaticReflection.GetMemberName<string>(x => x.LastIndexOf(','));
他的完整代码:
public static class StaticReflection
{
public static string GetMemberName<T>(
this T instance,
Expression<Func<T, object>> expression)
{
return GetMemberName(expression);
}
public static string GetMemberName<T>(
Expression<Func<T, object>> expression)
{
if (expression == null)
{
throw new ArgumentException(
"The expression cannot be null.");
}
return GetMemberName(expression.Body);
}
public static string GetMemberName<T>(
this T instance,
Expression<Action<T>> expression)
{
return GetMemberName(expression);
}
public static string GetMemberName<T>(
Expression<Action<T>> expression)
{
if (expression == null)
{
throw new ArgumentException(
"The expression cannot be null.");
}
return GetMemberName(expression.Body);
}
private static string GetMemberName(
Expression expression)
{
if (expression == null)
{
throw new ArgumentException(
"The expression cannot be null.");
}
if (expression is MemberExpression)
{
// Reference type property or field
var memberExpression =
(MemberExpression) expression;
return memberExpression.Member.Name;
}
if (expression is MethodCallExpression)
{
// Reference type method
var methodCallExpression =
(MethodCallExpression) expression;
return methodCallExpression.Method.Name;
}
if (expression is UnaryExpression)
{
// Property, field of method returning value type
var unaryExpression = (UnaryExpression) expression;
return GetMemberName(unaryExpression);
}
throw new ArgumentException("Invalid expression");
}
private static string GetMemberName(
UnaryExpression unaryExpression)
{
if (unaryExpression.Operand is MethodCallExpression)
{
var methodExpression =
(MethodCallExpression) unaryExpression.Operand;
return methodExpression.Method.Name;
}
return ((MemberExpression) unaryExpression.Operand)
.Member.Name;
}
}
请尝试使用 c# 的来电者信息功能
请参考网址:https://msdn.microsoft.com/en-us/library/hh534540.aspx