2012-06-05 13 views
8

ich folgende Dienstprogramm So verwenden Sie den Namen eines Feldes/Eigenschaft von einer Instanz einer Klasse zu erhalten ...Holen Sie sich den Namen eines Feldes aus einer Klasse ohne eine Instanz

public static string FieldName<T>(Expression<Func<T>> Source) 
{ 
    return ((MemberExpression)Source.Body).Member.Name; 
} 

Dies ermöglicht es mir zu wie folgt vorgehen:

public class CoolCat 
{ 
    public string KaratePower; 
} 

public class Program 
{ 
    public static Main() 
    { 
     public CoolCat Jimmy = new CoolCat(); 

     string JimmysKaratePowerField = FieldName(() => Jimmy.KaratePower); 
    } 
} 

Dies ist für die Serialisierung und andere Zeiten, in denen ich eine String-Darstellung des Feldnamens benötigen.

Aber jetzt, ich möchte in der Lage sein, den Feldnamen OHNE eine Instanz der Klasse zu bekommen - zum Beispiel, wenn ich eine Tabelle aufstellen und die FieldNames der Spalten dynamisch mit tatsächlichen Feldern in a verknüpfen will Klasse (so Refactorings, etc. wird es nicht brechen).

Grundsätzlich Ich fühle mich wie ich ganz einfach nicht die Syntax bekommen, wie dies zu erreichen, aber ich glaube, dass es so etwas wie folgt aussehen:

public static string ClassFieldName<T>(Func<T> PropertyFunction) 
{ 
    // Do something to get the field name? I'm not sure whether 'Func' is the right thing here - but I would imagine that it is something where I could pass in a lambda type expression or something of the sort? 
} 

public class Program 
{ 
    public static Main() 
    { 
     string CatsPowerFieldName = ClassFieldName<CoolCat>((x) => x.KaratePower); 

     // This 'CatsPowerFieldName' would be set to "KaratePower". 
    } 
} 

Ich hoffe, das macht Sinn - ich Ich bin nicht sehr gut mit dem Vokabular rund um dieses Thema, also weiß ich, dass die Frage ein wenig vage ist.

Antwort

3

Ich habe zwei Methoden, die ich verwende, um dies zu tun.

Die erste ist eine Erweiterungsmethode, die für jedes Objekt verwendet werden kann.

public static string GetPropertyName<TEntity, TProperty>(this TEntity entity, Expression<Func<TEntity, TProperty>> propertyExpression) 
{ 
    return propertyExpression.PropertyName(); 
} 

, die wie

public CoolCat Jimmy = new CoolCat(); 
string JimmysKaratePowerField = Jimmy.GetPropertyName(j => j.KaratePower); 

Das zweite ich, wenn ich ein Objekt, nicht verwenden verwendet wird.

public static string PropertyName<T>(this Expression<Func<T, object>> propertyExpression) 
{ 
     MemberExpression mbody = propertyExpression.Body as MemberExpression; 

     if (mbody == null) 
     { 
      //This will handle Nullable<T> properties. 
      UnaryExpression ubody = propertyExpression.Body as UnaryExpression; 

      if (ubody != null) 
      { 
       mbody = ubody.Operand as MemberExpression; 
      } 

      if (mbody == null) 
      { 
       throw new ArgumentException("Expression is not a MemberExpression", "propertyExpression"); 
      } 
     } 

     return mbody.Member.Name; 
} 

Dies kann wie so

string KaratePowerField = Extensions.PropertyName<CoolCat>(j => j.KaratePower); 
+0

Ich mag diese Lösung wirklich - könnten Sie vielleicht über den Abschnitt, den Sie mit Nullable Eigenschaften hinzugefügt hinzufügen? Wann würde dieser Codeabschnitt verwendet werden? – William

+0

Wenn KaratePower eine 'Nullable ' oder 'T?' Wie 'int?' Oder 'DateTime?' Ist, dann ist der Body kein MemberExpression, sondern ein UnaryExpression. Von dort müssen Sie den Operanden UnaryExpression nehmen, um die korrekte MemberExpression zu erhalten. – cadrell0

4

Was Sie versuchen zu tun ist einer der Gründe, erstellt Microsoft System.Reflection Versuchen this:

using System.Reflection; // reflection namespace 

public static List<Type> GetClassPropertyNames(Type myClass) 
     { 
      PropertyInfo[] propertyInfos; 
      propertyInfos = myClass.GetProperties(BindingFlags.Public); 

      List<Type> propertyTypeNames = new List<Type>(); 

      // write property names 
      foreach (PropertyInfo propertyInfo in propertyInfos) 
      { 
       propertyTypeNames .Add(propertyInfo.PropertyType); 
      } 

      return propertyNames; 

     } 
+0

Hinweis verwendet werden, dass dies alle öffentlichen statischen Eigenschaften zurückzukehren. Im Beispiel wird ein nicht statisches Feld verwendet. –

+0

Ich bin mir nicht sicher, dass dies mir hilft - ich möchte eine Methode haben, die ich aufrufen kann, die den String-Namen des Feldes einer bestimmten Klasse zurückgibt - wie kann ich das Obige in etwas Ähnliches verwandeln? – William

+0

@William Ich habe mein Beispiel mit Ihrer Anfrage aktualisiert, Sie können es aufrufen: GetClassPropertyNames (typeof (CoolCat)); –

2

I Reflexion glauben verwendet, wird hier nützlich sein. Ich habe VS gerade nicht bei mir, aber ich bin mir sicher, dass Sie etwas wie typeof (class) .GetMembers() tun können. Mein Spiegelbild ist ein wenig eingerostet.