2011-02-02 60 views

Respuesta

69

Mientras que el código para crear una costumbre Attribute es bastante simple, es mucho más importante que usted entienda lo que son atributos:

atributos son metadatos recopilados 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.

Así que, por ejemplo, echemos un vistazo a Validation Application Block, desde Enterprise Library. Si nos fijamos en 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 anterior, uno podría suponer que El código siempre será validado, siempre que sea cambiado, de acuerdo a las reglas del Validador (en el ejemplo, tener al menos 8 caracteres y como máximo 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 ser utilizados por otros métodos/clases/etc.

+0

realmente me gusta la respuesta y especialmente ", una pregunta más puedo poner la misma condición en la declaración del conjunto del código anterior así que ¿cómo se diferencia de las atribuciones, –

+1

@slash: ¿Puedes volver a formular eso? No entendí la pregunta. –

+1

Creo que la barra indicaba la diferencia entre usar los atributos y poner el código de validación real dentro del setter de la propiedad. Respuesta: Al escribir código dentro del setter se puede hacer para validar el valor, usando solo atributos no se validará como tal Los atributos son solo "metadatos". Otro código en otro lugar debería interesarle en los atributos que utiliza, leerlos y realizar acciones basadas en ellos. Un ejemplo típico es una biblioteca de validación, como se mencionó en @BrunoBrant. – romar

190

Se empieza por escribir una clase que deriva de Attribute:

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

entonces se podría decorar cualquier cosa (clase, método, propiedad, ...) con este atributo:

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

} 

y finalmente usaría 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 
} 

Puede limitar los tipos de objetivos a los que este atributo personalizado se podría aplicar 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 acerca de los atributos:

  • atributos son metadatos.
  • Se hornean en el conjunto al en tiempo de compilación, lo que tiene implicaciones muy serias sobre cómo se pueden establecer sus propiedades. Solo se aceptan los valores constantes (conocidos en tiempo de compilación)
  • La única forma de hacer sentido y 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.
+1

Donde, en qué función/clase, voy a 'utilizar la reflexión para buscarlo' –

+0

@Hasan A Yousef, por ejemplo en Entity Framework hay un atributo" Clave "que dice al marco: Esta propiedad debe ser considerada como clave principal . Al crear ORM, los atributos son muy útiles. – Parsa

+0

¿Cómo se accede a un atributo personalizado en una propiedad y no en una clase? – Canvas

6

Utilizando/copia Darin Dimitrov's great response, esto es cómo acceder a un atributo personalizado en una propiedad y no una clase:

La propiedad decorada [de la clase Foo]:

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

de obtenerlo:

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

importantes gracias a ti, Darin !!

Cuestiones relacionadas