通过指出来获取Method的名称?

时间:2015-06-12 10:39:12

标签: c# .net reflection

我有一个看起来像MyClass.SpecialMethod()的成员我需要将此方法的名称作为字符串发送到另一个方法。我知道我可以使用TypeOf.GetMethods(..).Name但是...将被硬编码,如果SpecialMethod更改了名称,则会出现问题。

所以我想做的就是这样的事情

TypeOf(MyClass).GetMethod(MyClass.SpecialMethod).Name

这是可行的,如果是的话,怎么样?

我知道我可以从方法中获取当前方法的名称,但此时它已经很晚了。

5 个答案:

答案 0 :(得分:3)

如果您可以使用nameof()作为Jason suggested,请使用它。

如果不这样做,则编写此辅助方法:

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() 在编译时被解析时间即可。这可能是性能上的巨大差异(如果它是一个问题)。

答案 1 :(得分:2)

如果您选择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)));
    }
  }
}

答案 2 :(得分:2)

<config> <frontend> <layout> <updates> <contactredirect> <file>contactredirect.xml</file> </contactredirect> </updates> </layout> </frontend> </config> 方式:

<layout version="0.1.0">
    <contacts_index_index translate="label">
        <reference name="contacts.form">
            <action method="setTemplate">
                <template>contactredirect/form.phtml</template>
            </action>
        </reference>
    </contacts_index_index>
</layout>

请注意, ...

使用它像:

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;
}

答案 3 :(得分:2)

C#6 nameof 非常整洁。

目前,您可以在.NET 4.5中使用 CallerMemberName 属性,但如果您无法使用该属性,或者该名称不是来自调用者,则可以从Expression中提取名称。 Someone已经为此做了一个实用工具。以下是他的代码。它生成代码refactoring-friendly

工作原理:

//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;
    }
}

答案 4 :(得分:0)

请尝试使用c#的

请参阅网址:https://msdn.microsoft.com/en-us/library/hh534540.aspx