Atributos en C #

Sé que C # (y .NET en general) es grande en atributos. Sin embargo, a pesar de que he progtwigdo en C # durante muchos años, no me he encontrado alguna vez utilizándolos. ¿Alguien me ayudaría a comenzar con ellos y me explicará cuál es el mejor para usarlos?

Gracias

De Pro C # 2008 y .NET 3.5 Platform, cuarta edición de Andrew Troelsen

Comprender la progtwigción atribuida

Una función de un comstackdor .NET es generar descripciones de metadatos para todos los tipos definidos y referenciados. Además de estos metadatos estándar contenidos en cualquier ensamblaje, la plataforma .NET proporciona una forma para que los progtwigdores inserten metadatos adicionales en un ensamblaje utilizando atributos. En pocas palabras, los atributos no son más que anotaciones de código que se pueden aplicar a un tipo determinado (clase, interfaz, estructura, etc.), miembro (propiedad, método, etc.), ensamblaje o módulo. La idea de anotar código utilizando atributos no es nueva. COM IDL proporcionó numerosos atributos predefinidos que permitieron a los desarrolladores describir los tipos contenidos dentro de un servidor COM dado. Sin embargo, los atributos COM eran poco más que un conjunto de palabras clave. Si un desarrollador COM necesitaba crear un atributo personalizado, él o ella podría hacerlo, pero se hacía referencia en el código por un número de 128 bits (GUID), que era engorroso en el mejor de los casos. A diferencia de los atributos COM IDL (que nuevamente eran simplemente palabras clave), los atributos .NET son tipos de clase que extienden la clase abstracta abstracta System.Attribute. A medida que explora los espacios de nombres .NET, encontrará muchos atributos predefinidos que puede usar en sus aplicaciones. Además, puede crear atributos personalizados para calificar aún más el comportamiento de sus tipos creando un nuevo tipo derivado de Attribute. Comprenda que cuando aplica atributos en su código, los metadatos integrados son esencialmente inútiles hasta que otra pieza de software refleje explícitamente la información. Si este no es el caso, la propaganda de los metadatos incrustados en el conjunto se ignora y es completamente inofensiva.

Consumidores de atributos

Como podría suponer, .NET 3.5 Framework SDK se entrega con numerosas utilidades que de hecho buscan diversos atributos. El comstackdor de C # (csc.exe) en sí mismo ha sido preprogtwigdo para descubrir la presencia de varios atributos durante el ciclo de comstackción. Por ejemplo, si el comstackdor de C # encuentra el atributo [CLSCompliant], comprobará automáticamente el elemento atribuido para asegurarse de que expone solo las construcciones que cumplen con CLS. A modo de otro ejemplo, si el comstackdor de C # descubre un elemento atribuido con el atributo [Obsoleto], mostrará una advertencia del comstackdor en la ventana Lista de errores de Visual Studio 2008. Además de las herramientas de desarrollo, numerosos métodos en las bibliotecas de clases base .NET están preprogtwigdos para reflejar atributos específicos. Por ejemplo, si desea persistir en el estado de un objeto para archivar, todo lo que debe hacer es anotar su clase con el atributo [Serializable]. Si el método Serialize () de la clase BinaryFormatter encuentra este atributo, el objeto se conservará automáticamente en el archivo en un formato binario compacto. .NET CLR también está al acecho de la presencia de ciertos atributos. Quizás el atributo .NET más famoso es [WebMethod]. Si desea exponer un método a través de solicitudes HTTP y codificar automáticamente el valor de retorno del método como XML, simplemente aplique [WebMethod] al método y el CLR maneja los detalles. Más allá del desarrollo de servicios web, los atributos son críticos para el funcionamiento del sistema de seguridad .NET, Windows Communication Foundation y la interoperabilidad COM / .NET (y así sucesivamente). Finalmente, puede crear aplicaciones que estén progtwigdas para reflejar sus propios atributos personalizados, así como cualquier atributo en las bibliotecas de clases base de .NET. Al hacerlo, esencialmente puede crear un conjunto de “palabras clave” entendidas por un conjunto específico de conjuntos.

Aplicando Atributos en C #

La biblioteca de clases base .NET proporciona una serie de atributos en varios espacios de nombres. A continuación se muestra una instantánea de algunos, pero por ningún motivo todos los atributos predefinidos.

Un pequeño muestreo de atributos predefinidos

[CLSCompliant]

Aplica el elemento anotado para cumplir con las reglas de la Especificación del lenguaje común (CLS). Recuerde que se garantiza que los tipos compatibles con CLS se utilizarán sin problemas en todos los lenguajes de progtwigción .NET.

[DllImport]

Permite que el código .NET haga llamadas a cualquier biblioteca de código no administrada en C o C ++, incluida la API del sistema operativo subyacente. Tenga en cuenta que [DllImport] no se utiliza al comunicarse con el software basado en COM.

[Obsoleto]

Marca un tipo o miembro obsoleto. Si otros progtwigdores intentan utilizar dicho elemento, recibirán una advertencia del comstackdor que describirá el error de sus formas.

[Serializable]

Marca una clase o estructura como “serializable”, lo que significa que puede mantener su estado actual en una secuencia.

[NonSerialized]

Especifica que un campo determinado en una clase o estructura no debe persistir durante el proceso de serialización.

[WebMethod]

Marca un método como invocable mediante solicitudes HTTP e instruye al CLR para que serialice el valor de retorno del método como XML.

Construyendo atributos personalizados

El primer paso para crear un atributo personalizado es crear una nueva clase derivada de System.Attribute. Ejemplo:

// A custom attribute. public sealed class VehicleDescriptionAttribute : System.Attribute { private string msgData; public VehicleDescriptionAttribute(string description) { msgData = description; } public VehicleDescriptionAttribute() { } public string Description { get { return msgData; } set { msgData = value; } } } 

Como puede ver, VehicleDescriptionAttribute mantiene una cadena interna privada (msgData) que puede establecerse usando un constructor personalizado y manipularse usando una propiedad type (Descripción). Más allá del hecho de que esta clase se derivó de System.Attribute, no hay nada exclusivo de esta definición de clase.

Por razones de seguridad, se considera una práctica recomendada de .NET diseñar todos los atributos personalizados como sellados. De hecho, Visual Studio 2008 proporciona un fragmento de código llamado Atributo que arrojará un nuevo Sistema. Clase derivada de atributos en su ventana de código.

Los atributos obtienen más uso en el código dirigido a otros progtwigdores o entre distintas partes de un progtwig, en lugar de un código dirigido a usuarios finales.

Por ejemplo, podría usar atributos para importar un archivo DLL, indicar cómo interactuarían los tipos con Visual Studio (diseñador visible, IntelliSense ayuda, paso a paso del depurador, etc.), cómo serializarlos, indicar que un tipo es obsoleto, describir valores predeterminados, descripciones, manejar el acceso COM, etc.

Esas son cosas que son en gran parte invisibles para el usuario final y que un progtwigdor único podría colocar en otro lugar en el código fuente. Pero son útiles cuando solo el binario comstackdo está disponible y no la fuente.

Me gusta usar atributos como metadatos en mi código. Hemos creado algunos atributos simples que nos permiten etiquetar quién escribió qué código, cuándo y por qué. Esto nos permite tener ambos cambios documentados en el código y en el tiempo de ejecución. Si hay alguna excepción durante el tiempo de ejecución, podemos inspeccionar la stack de llamadas, observar los atributos de los métodos en el camino y rastrear a las personas responsables:

 [Author("Erich", "2009/04/06", Comment = "blah blah blah")] public void MyFunction() { ... } 

Por supuesto, podríamos usar nuestro control de fuente para ver quién ingresó el código, pero esto que encontré hace que la información esté más disponible en el lugar donde la necesite. Además, si alguna vez cambiamos el control de fuente, esa información no se perderá, ya que persiste en el código.

Los atributos son una forma de progtwigción declarativa, ‘similar’ a la creación de su UI en XAML. ‘Marca’ piezas de código (clases, métodos, propiedades, lo que sea) con un atributo para que luego pueda reunir todas las piezas marcadas de una manera específica y luego hacer algo estándar con todas ellas.

P.ej. Tenga en cuenta la situación en la que tiene determinadas secciones de código que desea ejecutar una vez cada vez que se inicia su aplicación. En un modelo de progtwigción (no atributo) vas a tu método principal y llamas explícitamente esos métodos de inicio. Con los atributos, simplemente reúne todos los métodos que ha marcado con su atributo ‘init’ y los llama mediante reflexión.

El mismo patrón se aplica a acciones como serialización, persistencia y otras cosas …

Creo que quieres decir que no usas (o usas con frecuencia) atributos personalizados definidos?

En mi proyecto actual, hago un uso intensivo de los atributos personalizados, pero el hecho de que debes tenerlo en cuenta es que el uso de atributos no debe ser un objective en sí mismo.

Es una herramienta / propósito para llegar a una solución dada.

A veces uso atributos personalizados en combinación con un tejedor como PostSharp, para decorar los métodos donde se debe aplicar algo de tejido en tiempo de comstackción.

En mi proyecto actual, también uso atributos para decorar ciertos tipos con información adicional … Pero creo que ya publiqué sobre esto aquí antes: ¿ Usos geniales de Atributos o Anotaciones (CLR o Java)?

Yo uso atributos para lo siguiente:

  • Comunicarse con una architecture de plug-in
  • Contando a otro framework qué hacer con el código (NUnit, por ejemplo)
  • Agregar metadatos para usar con otro código (ver PropertyGrid)
  • Asignación de objetos a bases de datos (ver Castle ActiveRecord)
  • Al escribir mis propias API para permitir a los usuarios comunicar metadatos
  • En código de marco para decirle al depurador que se salte el

Esos están fuera de mi cabeza. Los uso en muchos otros lugares

Los atributos son muy buenos para describir el comportamiento de tiempo de ejecución de su código que es ortogonal al código en cuestión. Por ejemplo, en una clase llamada Cliente, usted modelaría un cliente, ¿verdad? Pero es posible que no desee modelar o describir la forma en que un objeto del Cliente se serializa.

Agregar atributos a su clase de Cliente le permite decirle a otra parte del tiempo de ejecución cómo debe tratar con su Cliente.

MSTest y NUnit hacen uso de los atributos para indicarle al marco de prueba cómo debe usar las clases que definen los dispositivos de prueba.

ASP.NET MVC usa un atributo para indicarle a la infraestructura de mvc qué métodos en las clases debe tratar como acciones de controlador.

Por lo tanto, cualquier lugar donde tenga un comportamiento en tiempo de ejecución que desee modelar atributos puede ser útil.

La definición de atributo de clase está disponible aquí

ClassInterfaceAttribute : indica el tipo de interfaz de clase que se generará para una clase expuesta a COM, si se genera una interfaz.

ComDefaultInterfaceAttribute : especifica una interfaz predeterminada para exponer a COM. Esta clase no puede heredarse.

ComVisibleAttribute : controla la accesibilidad de un tipo o miembro administrado individual, o de todos los tipos dentro de un ensamblaje, a COM.