Cómo crear un atributo personalizado en C #

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

¿Puede alguien explicarme un ejemplo muy básico de un atributo personalizado con código?

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

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

Entonces, por ejemplo, veamos el Bloqueo de aplicaciones de validación , de Enterprise Library . Si miras un ejemplo de código, verás:

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

Del fragmento de código anterior, se puede suponer que el Código siempre se validará, siempre que se cambie, 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, verificará si el contenido infringe la regla informada por el atributo.

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

Empiezas 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 la reflexión para buscarla:

 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 } 

Podría limitar los tipos de destino a los que se podría aplicar este atributo personalizado utilizando el atributo AttributeUsage :

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

Cosas importantes que debes saber sobre los atributos:

  • Los atributos son metadatos.
  • Se incorporan al ensamblaje en tiempo de comstackción, lo que tiene implicaciones muy serias de cómo puede establecer sus propiedades. Sólo se aceptan valores constantes (conocidos en tiempo de comstackción)
  • La única forma de dar sentido y uso a los atributos personalizados es usar Reflection . Entonces, si no usa la reflexión en el tiempo de ejecución para buscarlos y decorar algo con un atributo personalizado, no espere que ocurra mucho.
  • El tiempo de creación de los atributos no es determinista. El CLR crea una instancia de ellos y usted no tiene ningún control sobre ellos.

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 clase Foo ]:

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

Ir a buscarlo:

 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 , también:

 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 } } 

Mayor gracias a ti, Darin !!