2012-06-05 5 views
8

Quindi io uso il seguente programma di utilità per ottenere il nome di un campo/proprietà da un'istanza di una classe ...Prendi il nome di un campo da una classe senza un'istanza

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

Questo mi permette di effettuare le seguenti operazioni:

public class CoolCat 
{ 
    public string KaratePower; 
} 

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

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

Questo è grande per la serializzazione e altre volte in cui ho bisogno di una rappresentazione di stringa del nome del campo.

Ma ora, voglio essere in grado di ottenere il nome del campo SENZA avere un'istanza della classe - per esempio, se sto impostando una tabella e voglio collegare dinamicamente i FieldNames delle colonne ai campi effettivi in ​​un classe (quindi i refactoring, ecc. non lo romperanno).

In sostanza, mi sento come se proprio non riesce quasi mai la sintassi di come per ottenere questo risultato, ma immagino che sarà simile a questa:

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". 
    } 
} 

Spero che abbia un senso - I' Non sono molto bravo con il vocabolario su questo argomento, quindi so che la domanda è un po 'vaga.

risposta

3

Ho due metodi che uso per fare questo.

Il primo è un metodo di estensione che può essere utilizzato su qualsiasi oggetto.

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

Che viene utilizzato come

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

La seconda che uso quando non ho un oggetto.

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

Questo può essere usato in questo modo

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

Mi piace molto questa soluzione: potresti approfondire la sezione che hai aggiunto alla gestione delle proprietà di Nullable ? Quando si utilizzerà questa sezione di codice? – William

+0

Se KaratePower è un 'Nullable ' o 'T?' Come 'int?' O 'DateTime?', Il corpo non sarà un MemberExpression, sarà un UnaryExpression. Da lì, è necessario prendere l'Operando di UnaryExpression per ottenere la MemberExpression corretta. – cadrell0

4

cosa si sta cercando di fare è una delle ragioni Microsoft ha creato System.Reflection Prova 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

Si noti che questo restituirà tutte le proprietà statiche pubblici. Nell'esempio viene utilizzato un campo non statico. –

+0

Non sono sicuro che questo mi aiuti - Voglio avere un metodo che posso chiamare che restituisce il nome della stringa del campo di una determinata classe - come posso trasformare il precedente in qualcosa del genere? – William

+0

@William Ho aggiornato il mio esempio con la tua richiesta, puoi chiamarlo usando: GetClassPropertyNames (typeof (CoolCat)); –

2

Credo utilizzando la riflessione sarà utile qui. Non ho VS con me adesso, ma sono sicuro che puoi fare qualcosa come typeof (class) .GetMembers(). Il mio riflesso è un po 'arrugginito.

Problemi correlati