2009-01-29 13 views
66

Quiero obtener el PropertyInfo para una propiedad específica. Podría utilizar:¿Cómo obtener el PropertyInfo de una propiedad específica?

foreach(PropertyInfo p in typeof(MyObject).GetProperties()) 
{ 
    if (p.Name == "MyProperty") { return p } 
} 

Pero tiene que haber una manera de hacer algo similar a

typeof(MyProperty) as PropertyInfo 

está allí? ¿O estoy atrapado haciendo una comparación de cadenas inseguras?

Saludos.

Respuesta

33

Puede utilizar el nuevo operador nameof() que forma parte de C# 6 y disponible en Visual Studio 2015 . Más información here.

Para su ejemplo se debería utilizar:

PropertyInfo result = typeof(MyObject).GetProperty(nameof(MyObject.MyProperty)); 

el compilador convertir nameof(MyObject.MyProperty) a la "MyProperty" cadena pero se gana la ventaja de ser capaz de refactorizar el nombre de la propiedad sin tener que acordarse de cambiar la cadena de porque Visual Studio, ReSharper y similares saben cómo refactorizar los valores nameof().

+1

Si pudiera ser un poco más claro si su ejemplo comenzó con 'PropertyInfo result =' en lugar de 'var result =' . – DavidRR

10

usted puede hacer esto:

typeof(MyObject).GetProperty("MyProperty") 

Sin embargo, puesto que C# no tiene un tipo de "símbolo", no hay nada que le ayudará a evitar el uso de cadenas. ¿Por qué llamas a este tipo, inseguro, por cierto?

+32

¿Porque no se evalúa en tiempo de compilación? Si cambié el nombre de mi propiedad o escribí la cadena, no lo sabría hasta que se ejecutara el código. – tenpn

0

Reflection se utiliza para la evaluación del tipo de tiempo de ejecución. Por lo tanto, las constantes de cadena no se pueden verificar en tiempo de compilación.

+5

Eso es lo que OP está tratando de evitar. No estoy seguro si esto responde la pregunta. – nawfal

+0

Un buen punto respecto al tiempo de compilación frente al tiempo de ejecución y la intención original del OP aunque evitar cadenas codificadas aún parece ser la solución más limpia: evita la posibilidad de errores tipográficos, facilita la refactorización y hace que el código sea más limpio. –

120

Hay una manera .NET 3.5 con lambdas/Expression que no utiliza cuerdas ...

using System; 
using System.Linq.Expressions; 
using System.Reflection; 

class Foo 
{ 
    public string Bar { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     PropertyInfo prop = PropertyHelper<Foo>.GetProperty(x => x.Bar); 
    } 
} 
public static class PropertyHelper<T> 
{ 
    public static PropertyInfo GetProperty<TValue>(
     Expression<Func<T, TValue>> selector) 
    { 
     Expression body = selector; 
     if (body is LambdaExpression) 
     { 
      body = ((LambdaExpression)body).Body; 
     } 
     switch (body.NodeType) 
     { 
      case ExpressionType.MemberAccess: 
       return (PropertyInfo)((MemberExpression)body).Member; 
      default: 
       throw new InvalidOperationException(); 
     } 
    } 
} 
+0

Buena solución pero desafortunadamente no estoy usando .NET3.5. Aún así, ¡tic! – tenpn

+1

En 2.0, la respuesta de Vojislav Stojkovic es lo más cercano que puede obtener. –

+4

una pregunta: ¿por qué hay una prueba en "body is LambdaExpression" antes de extraer la propiedad .Body? ¿El selector no siempre es una LambdaExpression? – tigrou

Cuestiones relacionadas