Menu
Coddy logo textTech

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);  // John

Tambié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.

challenge icon

Desafío

Fácil

Construyamos 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 llamado PluginAttribute en el espacio de nombres PluginSystem. Tu atributo debe:
    • Heredar de Attribute
    • Tener dos propiedades de solo lectura: Name (string) y Version (string)
    • Aceptar ambos valores mediante su constructor
  • Plugins.cs: Crea varias clases de complementos en el espacio de nombres PluginSystem. Algunas deben estar decoradas con tu PluginAttribute, 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)
    Cada clase puede estar vacía; solo nos interesa descubrir sus metadatos mediante reflexión.
  • Program.cs: En tu archivo principal, utiliza la reflexión para descubrir todas las clases que tienen el atributo PluginAttribute. 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 Name y Version del 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})
        
    }
}
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de C# online