Saltar al contenido

Cómo crear un atributo personalizado en C #

Solución:

Empiece escribiendo una clase que se derive de Attribute:

public class MyCustomAttribute: Attribute
{
    public string SomeProperty { get; set; }
}

Entonces podrías decorar cualquier cosa (clase, método, propiedad, …) con este atributo:

[MyCustomAttribute(SomeProperty = "foo bar")]
public class Foo
{

}

y finalmente usarías la reflexión para buscarlo:

var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true);
if (customAttributes.Length > 0)
{
    var myAttribute = customAttributes[0];
    string value = myAttribute.SomeProperty;
    // TODO: Do something with the value
}

Puede limitar los tipos de destino a los que se puede aplicar este atributo personalizado mediante el atributo AttributeUsage:

/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute

Cosas importantes que debe saber sobre los atributos:

  • Los atributos son metadatos.
  • Se hornean en la asamblea en tiempo de compilación lo que tiene implicaciones muy serias sobre cómo podría establecer sus propiedades. Solo se aceptan valores constantes (conocidos en el momento de la compilación)
  • La única forma de tener algún sentido y uso de atributos personalizados es usar Reflection. Entonces, si no usa la reflexión en tiempo de ejecución para buscarlos y decorar algo con un atributo personalizado, no espere que suceda mucho.
  • El momento de creación de los atributos no es determinista. CLR crea una instancia de ellos y no tienes absolutamente ningún control sobre ellos.

Si bien el código para crear un atributo personalizado es bastante simple, es muy importante que comprenda qué atributos son:

Los atributos son metadatos compilados en su programa. Los atributos en sí mismos no agregan ninguna funcionalidad a una clase, propiedad o módulo, solo datos. Sin embargo, usando la reflexión, uno puede aprovechar esos atributos para crear funcionalidad.

Entonces, por ejemplo, veamos el Bloque de aplicación de validación, de la Biblioteca empresarial de Microsoft. Si observa un ejemplo de código, verá:

    /// <summary>
    /// blah blah code.
    /// </summary>
    [DataMember]
    [StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = ""{1}" must always have "{4}" characters.")]
    public string Code { get; set; }

A partir del fragmento anterior, se podría suponer que el código siempre se validará, siempre que se cambie, de acuerdo con las reglas del Validador (en el ejemplo, tenga al menos 8 caracteres y como máximo 8 caracteres). Pero la verdad es que el atributo no hace nada; como se mencionó anteriormente, solo agrega metadatos a la propiedad.

Sin embargo, la biblioteca empresarial tiene una Validation.Validate que examinará su objeto y, para cada propiedad, comprobará si el contenido viola la regla informada por el atributo.

Entonces, así es como debe pensar sobre los atributos: una forma de agregar datos a su código que luego podrían ser utilizados por otros métodos / clases / etc.

Utilizando / copiando la gran respuesta de Darin Dimitrov, así es como acceder a un atributo personalizado en una propiedad y no en una clase:

La propiedad decorada [of class Foo]:

[MyCustomAttribute(SomeProperty = "This is a custom property")]
public string MyProperty { get; set; }

Obteniéndolo:

PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck);
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
if (attribute.Length > 0)
{
    MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
    string propertyValue = myAttribute.SomeProperty;
}

Puede lanzar esto en un bucle y usar la reflexión para acceder a este atributo personalizado en cada propiedad de clase Foo, así como:

foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties())
{
    string propertyName = propertyInfo.Name;

    object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
    // Just in case you have a property without this annotation
    if (attribute.Length > 0)
    {
        MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
        string propertyValue = myAttribute.SomeProperty;
        // TODO: whatever you need with this propertyValue
    }
}

Muchas gracias a ti, Darin !!

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *