2008-12-23 16 views
6

? Sé que podría tener un atributo, pero eso es más trabajo de lo que quiero ... y no lo suficientemente general.¿Cómo obtengo el nombre de una propiedad de una propiedad en C# (2.0)

quiero hacer algo como

class Whotsit 
{ 
    private string testProp = "thingy"; 

    public string TestProp 
    { 
     get { return testProp; } 
     set { testProp = value; } 
    } 

} 

... 

Whotsit whotsit = new Whotsit(); 
string value = GetName(whotsit.TestProp); //precise syntax up for grabs.. 

donde yo esperaría que el valor sea igual a "TestProp"

pero no puedo por la vida de mí encontrar los métodos de reflexión derecho a escribir la Método GetName ...

EDITAR: ¿Por qué quiero hacer esto? Tengo una clase para almacenar las configuraciones leídas desde una tabla 'nombre', 'valor'. Esto está poblado por un método generalizado basado en la reflexión. Me gustaría bastante para escribir la inversa ...

/// <summary> 
/// Populates an object from a datatable where the rows have columns called NameField and ValueField. 
/// If the property with the 'name' exists, and is not read-only, it is populated from the 
/// valueField. Any other columns in the dataTable are ignored. If there is no property called 
/// nameField it is ignored. Any properties of the object not found in the data table retain their 
/// original values. 
/// </summary> 
/// <typeparam name="T">Type of the object to be populated.</typeparam> 
/// <param name="toBePopulated">The object to be populated</param> 
/// <param name="dataTable">'name, 'value' Data table to populate the object from.</param> 
/// <param name="nameField">Field name of the 'name' field'.</param> 
/// <param name="valueField">Field name of the 'value' field.</param> 
/// <param name="options">Setting to control conversions - e.g. nulls as empty strings.</param> 

public static void PopulateFromNameValueDataTable<T> 
     (T toBePopulated, System.Data.DataTable dataTable, string nameField, string valueField, PopulateOptions options) 
    { 
     Type type = typeof(T); 
     bool nullStringsAsEmptyString = options == PopulateOptions.NullStringsAsEmptyString; 

     foreach (DataRow dataRow in dataTable.Rows) 
     { 
      string name = dataRow[nameField].ToString(); 
      System.Reflection.PropertyInfo property = type.GetProperty(name); 
      object value = dataRow[valueField]; 

      if (property != null) 
      { 
       Type propertyType = property.PropertyType; 
       if (nullStringsAsEmptyString && (propertyType == typeof(String))) 
       { 
        value = TypeHelper.EmptyStringIfNull(value); 
       } 
       else 
       { 
        value = TypeHelper.DefaultIfNull(value, propertyType); 
       } 

       property.SetValue(toBePopulated, System.Convert.ChangeType(value, propertyType), null); 
      } 
     } 
    } 

hacer otras modificaciones: estoy solo en el código, tener una instancia de Whotsit y quiero obtener la cadena de texto de la propiedad 'TestProp'. Parece un tanto extraño, sé que puedo usar el literal "TestProp", o en el caso de mi clase con la función datatable, estaría en un bucle foreach de PropertyInfos. Solo tenía curiosidad ...

El código original tenía constantes de cadena, lo cual me pareció torpe.

+0

Es posible que tenga una respuesta aquí http://stackoverflow.com/a/1225702/661933 – nawfal

Respuesta

6

No, no hay nada que hacer esto. La expresión whotsit.TestProp evaluará la propiedad. Lo que queremos es el mítico operador "infoof":

// I wish... 
MemberInfo member = infoof(whotsit.TestProp); 

Tal como es, sólo se puede utilizar la reflexión para obtener la propiedad por su nombre - no del código. (O conseguir todas las propiedades, por supuesto Todavía no le ayuda con su muestra sin embargo..)

Una alternativa es utilizar un árbol de expresión:

Expression<Func<string>> =() => whotsit.TestProp; 

entonces examinar el árbol de expresión para obtener la propiedad.

Si nada de esto ayuda, ¿quizás podría decirnos más acerca de por qué quiere esta funcionalidad?

-1

El GetProperties on the Type class le dará la lista de propiedades de ese tipo.

Type t = whotsit.GetType(); 
PropertyInfo[] pis = t.GetProperties(); 
+0

utilización cierto, pero no tanto por lo que quiero hacer, ya que es la cadena del nombre que estoy buscando ... – kpollock

0

Lo que estás tratando de hacer no es posible. Usando el reflejo puede:

  • Obtenga una propiedad, campo o detalles del método a partir de su nombre de cadena.
  • Obtenga una lista de todas las propiedades, campos o métodos para un tipo determinado.

Su método GetName, cuando se le llama, recibe una cadena. GetMethod sabrá sobre la cadena, pero no conserva metadatos de propiedades de origen.

Fuera de interés, ¿por qué intentas hacer esto?

0

No creo que sea posible, la única manera de hacer esto es para iterar sobre propiedades:

class TestClass 
{ 
    private string _field; 

    public string MyProperty 
    { 
     get { return _field; } 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     TestClass test = new TestClass(); 
     PropertyInfo[] info = test.GetType().GetProperties(); 
     foreach(PropertyInfo i in info) 
      Console.WriteLine(i.Name); 
     Console.Read(); 
    } 
} 
+0

que todavía no me dará la capacidad de obtener el nombre de una propiedad de una instancia de la misma. – kpollock

3

Es posible (sin reflexión), pero sólo con la última C# 3.0

rápida & muy muy sucio

class Program 
{ 
    static void Main() 
    { 
     string propertyName = GetName(() => AppDomain.CurrentDomain); 
     Console.WriteLine(propertyName); // prints "CurrentDomain" 
     Console.ReadLine(); 
    } 

    public static string GetName(Expression<Func<object>> property) 
    { 
     return property.Body.ToString().Split('.').Last(); 
    } 
} 

actualización: Me acabo de dar cuenta de que Jon Skeet (¿alguien sorprendió? :) ya ha cubierto esta posibilidad, pero voy a mantener mi respuesta aquí solo en caso de que alguien esté interesado en algún ejemplo para empezar.

+0

También necesita .NET 3.5 (OP estados 2.0) –

+0

Lo sé, pero es una buena pregunta genérica y alguien con .NET 3.5 podría estar interesado en esto. –

+0

Estoy de acuerdo, no me sirve mucho, pero tal vez sea de utilidad para otros que vienen buscando. – kpollock

0

Kpollack, se dijo en un comentario anterior:

que todavía no me dará la posibilidad de obtener el nombre de una propiedad de una instancia del mismo.

Esto me lleva a creer que de alguna manera tiene una referencia a una propiedad. ¿Cómo obtuviste esta referencia? ¿Cuál es su tipo? ¿Podría proporcionar una muestra de código? Si es un objeto PropertyInfo, ya tiene lo que necesita; ya que este no parece ser el caso, estamos tratando con otra cosa, y me interesaría mucho ver con qué es lo que hacer tiene que trabajar.

P.S. Perdóname por parecer obtuso: es temprano, no he comido suficiente café, y no tengo mi IDE frente a mí. : -/

+0

Solo estoy en el código, tengo una instancia de Whotsit y quiero obtener la cadena de texto de la propiedad 'TestProp'. Parece un tanto extraño, sé que puedo usar el literal "TestProp", o en el caso de mi clase con la función datatable, estaría en un bucle foreach de PropertyInfos. Solo tenía curiosidad. – kpollock

0

FYI, traté de serializarlo para ver si, por casualidad, eso contiene el nombre de la propiedad, pero no tuve suerte.

inhábiles código de abajo:

Whotsit w = new Whotsit(); 
XmlSerializer xs = new XmlSerializer(w.TestProp.GetType()); 
TextWriter sw = new StreamWriter(@"c:\TestProp.xml"); 
xs.Serialize(sw, w.TestProp); 
sw.Close(); 
Cuestiones relacionadas