Gerardo Contijoch

Experiencias del día a día trabajando con .NET – ASP.NET, C#, ASP.NET MVC y demas…

DebuggerDisplayAttribute, una gran ayuda durante la depuración

Posted by Gerardo Contijoch en marzo 19, 2009

Hace un tiempo, revisando el código fuente de Castle.Core, uno de los componentes más importantes de Castle Microkernel, redescubrí (porque me había olvidado por completo de el) uno de los atributos más útiles que existen en el .NET Framework, DebuggerDisplayAttribute, el cuál nos permite personalizar la información que se muestra de un objeto o miembro en las ventanas de debug en Visual Studio así como también en los tooltips que aparecen al pasar el cursor sobre una variable.

Imaginemos que tenemos la clase Persona definida de la siguiente manera:

   1: public class Persona {
   2:     public string Nombre { get {/*...*/} set {/*...*/} }
   3:     public int Edad { get{/*...*/} set{/*...*/} }
   4:     public string Ciudad { get {/*...*/} set {/*...*/} }
   5:     public DateTime FechaDeNacimiento { get {/*...*/} set {/*...*/} }
   6: }

Normalmente mientras estamos depurando nuestra aplicación al inspeccionar una variable de tipo Persona la ventana QuickWatch (Inspección rápida) nos muestra la variable de la siguiente manera:

DebuggerDisplayAttribute-personaSinNombre

Se puede ver que el valor (columna Value) mostrado es el propio tipo de la variable, lo cual es redundante ya que el tipo aparece aclarado en su propia columna. En nuestro caso, eso no importa mucho ya que al expandir la variable vamos a ver todas sus propiedades, que es lo que realmente nos interesa, pero imaginen que tienen una lista de personas y precisan ubicar una en particular por alguna de sus propiedades. El trabajo de encontrarla puede ser muy tedioso:

DebuggerDisplayAttribute-personasSinNombre

Por eso para ayudarnos en estos casos esta DebuggerDisplayAttribute, el cual nos permite personalizar el valor mostrado en la columna Value de modo que podamos mostrar información más útil que el tipo de la variable o miembro bajo inspección. La propiedad más importante de este atributo es Value (de tipo string) que no es ni más ni menos que el valor a mostrar en la columna Value. Esta cadena puede contener llaves ({}) entre las cuales se puede especificar el nombre de un miembro cuyo valor queremos mostrar. Veamos como podemos decorar nuestra clase con este atributo:

   1: [DebuggerDisplay("Esta persona es {Nombre}")]
   2: public class Persona {
   3:    /*...*/
   4: }

Como resultado de este cambio, ahora la clase se va a ver así en la ventana de Debug:

DebuggerDisplayAttribute-personasConNombre

Si queremos sacar las comillas de los valores de tipo string, simplemente agregamos nq al miembro al que hacemos referencia:

   1: [DebuggerDisplay("Esta persona es {Nombre, nq}")]
   2: public class Persona {
   3:     /*...*/
   4: }

DebuggerDisplayAttribute-personaConNombreSinComillas

Incluso podemos incluir expresiones simples en nuestra descripción, pero sólo si estamos trabajando con C#:

   1: [DebuggerDisplay("Nombre: {Nombre, nq}, Año de nacimiento: {FechaDeNacimiento.Year}, ¿Es Rosarino?: {Ciudad == \"Rosario\" ? \"Sí\" : \"No\", nq}")]
   2: public class Persona {
   3:     /*...*/
   4: }

DebuggerDisplayAttribute-personaConNombreYExpresion

Otra forma de uso

El hecho de usar este atributo para decorar las clases puede no ser muy bien visto ya que es algo que afecta al entorno de desarrollo y no tiene relación con el contenido de nuestras clases en si. Es ajeno a nuestros sistemas y su presencia no afecta (o al menos no debería afectar) al comportamiento de los mismos. Estamos modificando nuestras clases solo porque queremos que Visual Studio nos las muestre como a nosotros más nos gusta.

Para evitar involucrar la lógica de nuestras clases con la lógica de presentación particular de Visual Studio (otro IDE puede no soportar este atributo e ignorarlo por completo) podemos usar este atributo a nivel de ensamblado y crear un nuevo ensamblado con únicamente la declaración del atributo. De este modo, tendremos que especificar, además de la información a mostrar, la clase o estructura sobre la cual queremos aplicarla mediante la propiedad Target.

Para que quede claro esto último lo voy a explicar. La idea de usarlo a nivel de ensamblado es crear una nueva dll (proyecto de tipo Librería de clases). Este proyecto tiene que referenciar al ensamblado que contiene el tipo que queremos decorar. Esto significa que si queremos decorar el tipo XmlDocument, entonces vamos a tener que referenciar al ensamblado System.Xml.dll, en cambio, si queremos decorar nuestra clase Persona, vamos a tener que referenciar a la dll que genere nuestro proyecto.

Una vez dentro del nuevo proyecto buscamos el archivo AssemblyInfo (o cualquier otro archivo, simplemente me parece que éste es el lugar más apropiado para hacerlo) y agregamos algo similar a esto (yo voy a usar mi ejemplo):

   1: [assembly: DebuggerDisplayAttribute("Nombre: {Nombre, nq}, Año de nacimiento: {FechaDeNacimiento.Year}, ¿Es Rosarino?: {Ciudad == \"Rosario\" ? \"Sí\" : \"No\", nq}",
   2:                                     Target = typeof(DebuggerDisplayAttributeTest.Persona))]

Como se ve, usé la propiedad Target para especificar al tipo al que vamos a decorar.

Ahora solo resta compilar este ensamblado y copiarlo al path de visualizadores de Visual Studio (solo el ensamblado, no sus dependencias). Este path varia dependiendo la versión de Visual Studio y Windows. En el caso de Windows Vista, el path tiene la siguiente forma:

%userprofile%\Documents\Visual Studio [VERSION_VS]\Visualizers

Sobre Windows XP y 2003 (e imagino que en 2000 también) es el siguiente:

%userprofile%\My Documents\Visual Studio [VERSION_VS]\Visualizers

Una vez copiado el ensamblado reiniciamos Visual Studio y listo, ya tenemos nuestras clases decoradas sin necesidad de modificar su código.

Si prestan atención, en la carpeta de visualizadores van a encontrar un archivo llamado autoexp.cs. Si inspeccionan el archivo, van a ver que clases de .NET Framework fueron decoradas con este atributo. Son libres de modificarlo (¡no sin antes hacer un backup!) y agregarle todo lo que quieran, pero es responsabilidad de ustedes compilarlo en algún proyecto.

Nos vemos en el próximo post!

Referencias:

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Una respuesta to “DebuggerDisplayAttribute, una gran ayuda durante la depuración”

  1. […] Scott Hanselman « DebuggerDisplayAttribute, una gran ayuda durante la depuración […]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: