2012-03-04 1 views
6

実行プロパティのプロパティ名を取得するにはどうすればよいですか。プロパティが "return"を使用する場合、 MethodBase.GetCurrentMethod()。Nameはプロパティの名前を返します。しかし、私が "yield return"を使うと、MethodBase.GetCurrentMethod()。Nameは "MoveNext"を返します。利回りを使用するときに実行プロパティ名を取得するにはどうすればよいですか?利回りを使用してプロパティ名を取得する方法

サンプルコード

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

の将来のバージョンでは動作しませんでしたか?私たちが必要性と文脈を理解すれば、おそらくあなたをより良く助けることができます。 – jason

+1

あなたは何を達成しようとしていますか? – Lloyd

+0

@ Jason、私はいくつかのユースケースを考えることができます。そのうちの1つがログに記録されます。良い質問です – kelloti

答えて

5

、コンパイラがどのように再編成しますメソッドは動作し、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

+0

名前は本当に難読化されていません。難読化は、意図的にここで起こるされていない、コードが何を隠そうとしています。彼らは有効なC#の名前ではありませんので、このような名前は、「言いようのない」と呼ばれています。また、あなたがここに 'StackTrace'を使用する必要はありません、' MethodBase.GetCurrentMethodは() 'で十分です。私はあなたの権利を想定 – svick

+0

@svickは、私はそれを私は今、それはハックです知るためのスタックトレースのアプローチでつもり助けを – kelloti

+0

感謝を編集しました。 – kumar

1

私は、ヘルパーメソッドにイテレータを移動します:あなたはおそらく推測できるように、ここでの問題はyield return文が背後に書き換えのビットを行うことです

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

シーンは、usingまたはラムダ式がどのように機能するかに似ています。これは実際に列挙子として実装され、yield returnというコードは、列挙子のMoveNextメソッドの一部です。

これは、リフレクションを使用して全体の問題である:それはあなたにそのコードが何であったかのあなたのコンパイル時考え方と一致しない場合があり、あなたのコード実行、およそランタイム情報を提供します。

これは、あなたが望む情報を簡単に取得する方法がないと言っている、長年にわたる方法です。 yield returnを次に別のメソッドに移動する場合、そのメソッド以外のコードは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; 
    } 
} 

はEDIT:私はそれを記録するために、短期的にはあなたを助ける疑うながら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; 
} 
+0

情報ありがとうございますCallerMemberNameの目を保つでしょう。他の制約のため、私はStackTraceソリューションを使用しています。 – kumar

関連する問題