Cómo obtener el valor de una propiedad por nombre mediante reflexión en C#: análisis para principiantes
\n\nImagine una situación: está escribiendo código en el que necesita acceder dinámicamente, sobre la marcha, a una propiedad de un objeto. El nombre de esta propiedad proviene, por ejemplo, de un archivo de configuración, de una solicitud JSON o lo ingresa el usuario. No se puede codificar rígidamente object.PropertyName porque no conoce el nombre de antemano. ¿Qué hacer?
Aquí es donde entra en juego la reflexión (reflection), un potente mecanismo de C# que permite examinar tipos de datos y sus miembros (propiedades, métodos, campos) durante la ejecución del programa. En este artículo, analizaremos la pregunta más popular en Stack Overflow: cómo obtener el valor de la propiedad de un objeto a partir de una cadena que contiene su nombre. Lo haremos con ejemplos reales, de lo simple a lo complejo, y veremos los errores comunes en los que tropiezan los principiantes.
\n\n¿Qué es la reflexión y para qué sirve?
\n\nLa reflexión en C# es la capacidad de un programa de "mirarse a sí mismo" y obtener información sobre sus propios tipos. El espacio de nombres System.Reflection proporciona clases como Type, PropertyInfo, MethodInfo, que le permiten:
- \n
- Conocer todas las propiedades y métodos de una clase. \n
- Crear instancias de clases sin el operador
new. \n - Invocar métodos y obtener/establecer valores de propiedades por sus nombres de cadena. \n
Sin la reflexión, no podría, por ejemplo, escribir un mapeador de objetos universal (como AutoMapper) o un serializador que funcione con cualquier tipo de datos.
\n\nEjemplo básico: obtener el valor de una propiedad por nombre
\n\nSupongamos que tenemos una clase simple Person:
public class Person\n{\n public string Name { get; set; }\n public int Age { get; set; }\n public string City { get; set; }\n}\n\nQueremos escribir un método que tome un objeto Person y una cadena con el nombre de la propiedad (por ejemplo, "Name" o "Age") y devuelva el valor de esa propiedad. Así es como se hace con reflexión:
using System;\nusing System.Reflection;\n\npublic static object GetPropertyValue(object obj, string propertyName)\n{\n if (obj == null) throw new ArgumentNullException(nameof(obj));\n if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("El nombre de la propiedad no puede estar vacío", nameof(propertyName));\n\n // Obtenemos el tipo del objeto\n Type type = obj.GetType();\n\n // Obtenemos la información de la propiedad por su nombre\n PropertyInfo propertyInfo = type.GetProperty(propertyName);\n\n // Verificamos si existe dicha propiedad\n if (propertyInfo == null)\n throw new ArgumentException($"La propiedad '{propertyName}' no se encontró en el tipo '{type.Name}'");\n\n // Obtenemos el valor de la propiedad\n return propertyInfo.GetValue(obj);\n}\n\nAhora usamos nuestro método:
\n\nvar person = new Person { Name = "Ana", Age = 30, City = "Madrid" };\n\nstring name = (string)GetPropertyValue(person, "Name");\nint age = (int)GetPropertyValue(person, "Age");\n\nConsole.WriteLine($"Nombre: {name}, Edad: {age}"); // Salida: Nombre: Ana, Edad: 30\n\n¡Funciona! Puntos clave:
\n- \n
obj.GetType()— obtiene el objetoTypeque describe el tipo de nuestro objeto. \n type.GetProperty("Name")— busca una propiedad pública con el nombre "Name". DevuelvePropertyInfoonullsi no se encuentra la propiedad. \n propertyInfo.GetValue(obj)— devuelve el valor de esa propiedad para la instancia específicaobj. \n
Matices importantes y errores comunes (lo que los juniors callan)
\n\n1. Sensibilidad a mayúsculas y minúsculas
\nEl método GetProperty distingue entre mayúsculas y minúsculas de forma predeterminada. Si especifica "name" en lugar de "Name", la propiedad no se