Atributos y Reflexión
Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 44 de 70.
Los atributos son etiquetas de metadatos que adjuntas a elementos de código como clases, métodos o propiedades. No cambian directamente la forma en que se ejecuta el código, pero proporcionan información que puede leerse en tiempo de ejecución. La reflexión es el mecanismo que lee estos metadatos.
Aplicas un atributo colocándolo entre corchetes encima del elemento de destino:
[Obsolete("Use NewMethod instead")]
public void OldMethod() { }
[Serializable]
public class Person
{
public string Name { get; set; }
}Puedes crear atributos personalizados heredando de Attribute:
public class AuthorAttribute : Attribute
{
public string Name { get; }
public AuthorAttribute(string name) => Name = name;
}
[Author("John")]
public class Calculator { }La reflexión te permite inspeccionar tipos y leer atributos en tiempo de ejecución mediante el espacio de nombres System.Reflection:
Type type = typeof(Calculator);
var attr = type.GetCustomAttribute<AuthorAttribute>();
Console.WriteLine(attr.Name); // JohnTambién puedes descubrir métodos y propiedades, e invocarlos dinámicamente:
MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
Console.WriteLine(method.Name);Los atributos y la reflexión impulsan muchos frameworks: las bibliotecas de serialización los usan para controlar la salida JSON, los frameworks de pruebas los usan para descubrir métodos de prueba y los contenedores de inyección de dependencias los usan para conectar servicios automáticamente.
Desafío
FácilConstruyamos un sistema de descubrimiento de complementos que utilice atributos personalizados y reflexión para encontrar y describir automáticamente las clases marcadas como complementos. Esto es similar a cómo los frameworks reales descubren componentes, métodos de prueba o endpoints de API durante la ejecución.
Organizarás tu código en tres archivos:
PluginAttribute.cs: Crea un atributo personalizado llamadoPluginAttributeen el espacio de nombresPluginSystem. Tu atributo debe:- Heredar de
Attribute - Tener dos propiedades de solo lectura:
Name(string) yVersion(string) - Aceptar ambos valores mediante su constructor
- Heredar de
Plugins.cs: Crea varias clases de complementos en el espacio de nombresPluginSystem. Algunas deben estar decoradas con tuPluginAttribute, y una no:ImageProcessor- marcada con[Plugin("Image Processor", "1.0")]DataExporter- marcada con[Plugin("Data Exporter", "2.5")]HelperUtility- NO marcada con ningún atributo (es simplemente una clase normal)
Program.cs: En tu archivo principal, utiliza la reflexión para descubrir todas las clases que tienen el atributoPluginAttribute. Para cada complemento descubierto, imprime su información. Deberás:- Obtener todos los tipos del ensamblado actual
- Comprobar si cada tipo tiene el atributo
PluginAttribute - Extraer y mostrar las propiedades
NameyVersiondel atributo
Utiliza System.Reflection para inspeccionar los tipos y recuperar atributos personalizados. El método GetCustomAttribute<T>() devuelve null si el atributo no está presente, por lo que puedes usarlo para filtrar qué clases son complementos reales.
Imprime cada complemento descubierto con este formato, uno por línea:
Plugin: {Name} (v{Version})Los complementos deben imprimirse en este orden: primero ImageProcessor y después DataExporter. La clase HelperUtility no debe aparecer en la salida, ya que carece del atributo.
Salida esperada:
Plugin: Image Processor (v1.0)
Plugin: Data Exporter (v2.5)Este desafío demuestra cómo los frameworks utilizan atributos como marcadores y la reflexión para descubrirlos; ¡la misma técnica impulsa los contenedores de inyección de dependencias, las bibliotecas de serialización y los frameworks de pruebas!
Pruébalo tú mismo
using System;
using System.Reflection;
using PluginSystem;
class Program
{
public static void Main(string[] args)
{
// TODO: Obtén todos los tipos del ensamblado actual
// Pista: Usa Assembly.GetExecutingAssembly().GetTypes()
// TODO: Recorre cada tipo y comprueba si tiene el PluginAttribute
// Pista: Usa type.GetCustomAttribute<PluginAttribute>()
// TODO: Si el atributo existe, imprime la información del plugin en el formato:
// Plugin: {Name} (v{Version})
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantesPractica por tu cuenta: Compilador de C# online