Как получить имя свойства при использовании return - PullRequest
6 голосов
/ 04 марта 2012

Как получить имя свойства исполняемого свойства.Если свойство использует «return», тогда MethodBase.GetCurrentMethod (). Name возвращает имя свойства.Но когда я использую метод «yield return» MethodBase.GetCurrentMethod (). Name возвращает «MoveNext»как получить имя исполняемого свойства, когда оно возвращает return?

Пример кода

    class Program
    {
       static void Main(string[] args)
       {

         var x = myProgram.Something;

         Console.ReadLine();
       }       
   }

public class myProgram
{
    public static IEnumerable<string> Something
    {
        get
        {
            string var = MethodBase.GetCurrentMethod().Name;
            for (int i = 0; i < 5; i++)
            {
                yield return var;
            }
        }
    }
}

Ответы [ 3 ]

5 голосов
/ 04 марта 2012

Как вы, вероятно, можете догадаться, проблема в том, что оператор yield return немного переписывает за кулисами, подобно тому, как это делает using или лямбда-выражение. На самом деле он реализован как перечислитель, а код, который вызывает yield return, является частью метода MoveNext в перечислителе.

Это общая проблема использования Reflection: она дает вам время выполнения информацию о вашем исполняемом коде, которая может не соответствовать вашему времени компиляции представления о том, что это был за код. 1011 *

Это многословный способ сказать, что нет простого способа получить нужную информацию. Если бы вы переместили yield return next в отдельный метод, то любой код вне этого метода не был бы частью MoveNext, но это может или не может выполнить то, что вам нужно. Вы больше не получаете имя метода, выполняющего yield return, вы получаете имя его вызывающего . Если это все, что вас волнует, это выглядит так:

public IEnumerable<string> Something
{
    get
    {
        var x = MethodBase.GetCurrentMethod().Name;
        return this.DoSomething(x);
    }
}

private IEnumerable<string> DoSomething(string x)
{
    for (int i = 0; i < 5; i++)
    {
        yield return x;
    }
}

РЕДАКТИРОВАТЬ: Хотя я сомневаюсь, что это поможет вам в краткосрочной перспективе, для записи, эта проблема также решается при использовании новых атрибутов C # 5. Поскольку атрибут CallerMemberName разрешается во время компиляции и, по-видимому, до того, как итератор был переписан в класс перечислителя, он создает имя свойства:

public IEnumerable<string> Something
{
    get
    {
        var x = this.GetCallerName();
        for (int i = 0; i < 5; i++)
        {
            yield return x;
        }
    }
}

private string GetCallerName([CallerMemberName] string caller = null)
{
    return caller;
}
5 голосов
/ 04 марта 2012

Как вы, наверное, заметили, компилятор реорганизует работу методов, и Something возвращает закрытый класс, который реализует IEnumerable. Таким образом, фактическое содержимое вашего метода появляется в методе MoveNext этого закрытого класса, поэтому MethodBase.GetCurrentMethod не возвращает то, что, как кажется, должно возвращаться.

Бывает, что имя частного класса получено из исходного имени метода, которое в данном случае равно <Enumerate>d__0. Таким образом, вы можете проанализировать исходное имя метода из фрейма стека.

static IEnumerable<string> Enumerate()
{
    var method = new StackTrace(true).GetFrame(0).GetMethod().DeclaringType.Name;
    yield return Regex.Replace(method, @".*<([^)]+)>.*", "$1");
} 

static void Main(string[] args)
{
    foreach (var @string in Enumerate())
    {
        Console.WriteLine(@string);
    }
}

Это, конечно, хак и может не сработать в будущих версиях .NET

1 голос
/ 04 марта 2012

Я бы переместил итератор в вспомогательный метод:

public class myProgram
{
    public static IEnumerable<string> Something
    {
        get
        {
            string var = MethodBase.GetCurrentMethod().Name;
            return GetSomethingInternal();
        }
    }

    private static IEnumerable<string> GetSomethingInternal()
    {
        for (int i = 0; i < 5; i++)
        {
            yield return i;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...