programacion orientada objetos metodos lenguaje comandos codigos clases avanzada atributos c# c#-4.0 custom-attributes

orientada - Cómo crear un atributo personalizado en C#



programacion avanzada c# (3)

Lo he intentado muchas veces pero todavía no puedo entender el uso de atributos personalizados (ya he pasado por muchos enlaces).

¿Alguien puede por favor explicarme un ejemplo muy básico de un atributo personalizado con código?


Comienza escribiendo una clase que se deriva 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 el reflejo 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 utilizando 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 el ensamblado en tiempo de compilación, lo que tiene implicaciones muy serias de cómo se pueden establecer sus propiedades. Solo se aceptan valores constantes (conocidos en tiempo de compilación)
  • La única forma de tener sentido y el uso de los 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 tiempo de creación de los atributos no es determinista. Ellos son instanciados por el CLR y usted no tiene absolutamente ningún control sobre él.

Si bien el código para crear un Attribute personalizado es bastante simple, es muy importante que comprenda cuáles son los atributos:

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, al usar la reflexión, se pueden aprovechar esos atributos para crear funcionalidad.

Entonces, por ejemplo, echemos un vistazo al Bloque de aplicaciones de validación , desde Enterprise Library . 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; }

Desde el fragmento de arriba, uno puede adivinar que el Código siempre será validado, siempre que se modifique, de acuerdo con las reglas del Validador (en el ejemplo, tiene al menos 8 caracteres y un máximo de 8 caracteres). Pero la verdad es que el atributo no hace nada, solo agrega metadatos a la propiedad.

Sin embargo, Enterprise Library tiene un método Validation.Validate que examinará su objeto, y para cada propiedad, comprobará si el contenido infringe la regla informada por el atributo.

Por lo tanto, así es como debería pensar en los atributos: una forma de agregar datos a su código que luego podrían usar otros métodos / clases / etc.


Utilizando / Copiando la gran respuesta de Darin Dimitrov , esta es la forma de acceder a un atributo personalizado en una propiedad y no en una clase:

La propiedad decorada [de la clase 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 la clase Foo , así:

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!