2008-11-07 10 views
34

Je suis en train d'écrire une fonction qui va tirer le nom d'une propriété et le type en utilisant la syntaxe comme ci-dessous:Obtenir le nom de la propriété et le type en utilisant l'expression lambda

private class SomeClass 
{ 
    Public string Col1; 
} 

PropertyMapper<Somewhere> propertyMapper = new PropertyMapper<Somewhere>(); 
propertyMapper.MapProperty(x => x.Col1) 

Est-il possible de transférer la propriété par à la fonction sans changements majeurs à cette syntaxe?

Je souhaite obtenir le nom et le type de propriété.

Ainsi, dans l'exemple ci-dessous je voudrais récupérer

Name = "Col1" et Type = "System.String"

Quelqu'un peut-il aider?

+0

Quelle est la plus grande image? Pourquoi ne pas simplement passer "Col1" comme nom de chaîne et utiliser la réflexion pour trouver ce membre? Qu'est-ce qui motive le lambda? – Brian

+12

Je travaille sur un ORM interne pour mon travail. Je veux facilement prendre en charge le changement de noms de propriété sans avoir à chercher une chaîne partout, en plus de donner une syntaxe propre (à mon avis) – pythonandchips

Répondre

59

assez est ici d'un exemple d'utilisation Expressions pour obtenir le nom d'une propriété ou d'un champ pour vous aider à démarrer:

public static MemberInfo GetMemberInfo<T, U>(Expression<Func<T, U>> expression) 
{ 
    var member = expression.Body as MemberExpression; 
    if (member != null) 
     return member.Member; 

    throw new ArgumentException("Expression is not a member access", "expression"); 
} 

Indicatif téléphonique ressemblerait à ceci:

public class Program 
{ 
    public string Name 
    { 
     get { return "My Program"; } 
    } 

    static void Main() 
    { 
     MemberInfo member = ReflectionUtility.GetMemberInfo((Program p) => p.Name); 
     Console.WriteLine(member.Name); 
    } 
} 

Un mot de prudence, cependant: la simple déclaration de (Program p) => p.Name implique effectivement un peu de travail (et peut prendre des quantités mesurables de temps). Envisagez de mettre en cache le résultat plutôt que d'appeler la méthode fréquemment.

+6

Rappelez-vous toujours qu'une expression lambda peut être convertie en un délégué ou un arbre d'expression. –

+1

Avertissement: l'implémentation de GetMemberInfo n'est pas très sûre - http://stackoverflow.com/questions/6658669/lambda-expression-not-returning-expected-memberinfo.Cela dit vous pouvez l'utiliser juste pour lire le nom. Mais l'information de membre retournée elle-même ne sera pas exacte. – nawfal

3

J'ai trouvé cela très utile.

public class PropertyMapper<T> 
{ 
    public virtual PropertyInfo PropertyInfo<U>(Expression<Func<T, U>> expression) 
    { 
     var member = expression.Body as MemberExpression; 
     if (member != null && member.Member is PropertyInfo) 
      return member.Member as PropertyInfo; 

     throw new ArgumentException("Expression is not a Property", "expression"); 
    } 

    public virtual string PropertyName<U>(Expression<Func<T, U>> expression) 
    { 
     return PropertyInfo<U>(expression).Name; 
    } 

    public virtual Type PropertyType<U>(Expression<Func<T, U>> expression) 
    { 
     return PropertyInfo<U>(expression).PropertyType; 
    } 
} 

J'ai fait cette petite classe pour suivre la demande originale. Si vous avez besoin du nom de la propriété que vous pouvez l'utiliser comme ceci:

PropertyMapper<SomeClass> propertyMapper = new PropertyMapper<SomeClass>(); 
string name = propertyMapper.PropertyName(x => x.Col1); 
2

Je pensais juste que je mettrais ce ici pour tirer parti de l'approche précédente.

public static class Helpers 
{ 
    public static string PropertyName<T>(Expression<Func<T>> expression) 
    { 
     var member = expression.Body as MemberExpression; 
     if (member != null && member.Member is PropertyInfo) 
      return member.Member.Name; 

     throw new ArgumentException("Expression is not a Property", "expression"); 
    } 
} 

Vous pouvez alors l'appeler de la façon suivante:

Helpers.PropertyName(() => TestModel.TestProperty); 

Je tiens également à souligner que, avec VS 2015 et C# 6.0, vous pouvez simplement utiliser NomDe.

https://msdn.microsoft.com/en-us/library/dn986596.aspx

3

Ceci peut être facilement fait en C# 6. Pour obtenir le nom de l'utilisation de la propriété opérateur NomDe.

nameof(User.UserId) 

et d'obtenir le type de propriété utiliser l'opérateur typeof.

typeof(User.UserId) 
Questions connexes