2012-03-04 21 views
6

Yürütme özelliğinin özellik adını nasıl alırım. Özellik "return" kullanırsa, MethodBase.GetCurrentMethod() Name, özelliğin adını döndürür. Ancak "getiri dönüşü" MethodBase.GetCurrentMethod() kullandığımda, adı "MoveNext" döndürür. Verim iadesi kullandığında yürütme özellik adını nasıl alabilirim?Verim dönüşü kullanıldığında özellik adı nasıl alınır

Bir yardımcı yöntem haline yineleyici hareket edeceğini

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

gelecekteki sürümlerinde çalışmaz ki? İhtiyacı ve içeriği anladıysak, size daha iyi yardımcı olabiliriz. – jason

+1

Neye ulaşmaya çalışıyorsunuz? – Lloyd

+0

@Jason, birkaç kullanım vakasını düşünebilirim - bunlardan sadece biri kayıt olabilir. Bu iyi bir soru – kelloti

cevap

5

, derleyici nasıl yeniden düzenleyen: CallerMemberName nitelik derleme zamanında çözümlenir yana yineleyici sayimm sınıfa yeniden yazılmıştır görünüşte önce ve bu özelliğin adını üretir yöntemler işe yarar ve bir şey IEnumerable uygulayan özel bir sınıf döndürür. Bu nedenle, yönteminizin gerçek içeriği bu özel sınıfın MoveNext yönteminde görünür, bu nedenle MethodBase.GetCurrentMethod geri dönmesi gerektiği gibi görünmüyor.

Özel sınıfın adı, bu durumda <Enumerate>d__0 olan özgün yöntem adından türetilir. Böylece, orijinal yöntem adını bir yığın çerçeveden ayrıştırabilirsiniz.

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

Bu, elbette, kesmek ve kolay kullanım durumu nedir .NET

+0

İsim gerçekten gizlenmedi.Obfüscation, kasten, kodun ne yaptığını gizlemeye çalışıyor, ki bu burada olmaz. Bunun gibi isimler, geçerli olmayan # # isimleri olmadıkları için "açıklanamaz" olarak adlandırılır. Ayrıca, burada 'StackTrace' kullanmanıza gerek yoktur, 'MethodBase.GetCurrentMethod() 'yeterlidir. – svick

+0

@svick Senin hakkını varsayalım, ben onu düzenledim – kelloti

+0

Yardım için teşekkürler şimdi bir hack olduğunu bilmek için stacktrace yaklaşımı ile gidiyorum. – kumar

1

Örnek Kod: muhtemelen tahmin edebileceğiniz gibi

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

, sorun burada yield return açıklamada arkasında yeniden yazma biraz yapmasıdır sahneler, bir using veya lambda ifadesinin yaptığı gibi. Aslında, numaralandırıcıda yield return yönteminin MoveNext yönteminin bir parçası olan kodu içeren bir numaralayıcı olarak uygulanmaktadır.

Bu Reflection kullanarak genel bir sorundur: o size derleme zamanı bu kod ne olduğunu fikri aynı olmayabilir infaz kodu hakkında çalışma zamanı bilgi verir.

Bu, istediğiniz bilgileri almanın kolay bir yolu olmadığını söyleyen uzun bir yoldur. yield return'u ayrı bir yönteme yerleştirecekseniz, bu yöntemin dışındaki herhangi bir kod, MoveNext'un bir parçası olmaz, ancak ihtiyacınız olanı gerçekleştirebilir veya gerçekleştiremeyebilir. Artık, yield return'u yürüten yöntemin adını almıyorsunuz, bunun adı arayanın numarasını alıyorsunuz. Bu önemsediğiniz tüm varsa o şuna benzer:

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: Ben kayıt için kısa vadede size yardımcı olacaktır şüphe ederken C# 5'in yeni özelliklerini kullanırken, bu sorun da çözüldü.

muhtemelen fark etmiş olduğunuz gibi
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

Bilgi için teşekkürler CallerMemberName için bir göz tutacaktır. Diğer kısıtlamalar nedeniyle StackTrace çözümüyle gidiyorum. – kumar