sábado, 22 de enero de 2011

Clases y métodos parciales

Una clase parcial permite dividir la definición de una clase en múltiples ficheros.
Después y en tiempo de compilación, los distintos ficheros en los que está definida la clase se unirán para formar una sola clase igual que si se hubiera definido inicialmente en un solo fichero.

La magia de combinar distintos ficheros de una misma clase se consigue a través de la palabra clave Partial (en realidad, no hace falta que cada definición parcial de la clase esté en un fichero distinto).

Lo cierto es que Visual Studio es bastante flexible con la definición de clases parciales y podemos ver cualquiera de los siguientes escenarios:

  • Un solo fichero con una sola clase con la palabra Partial (es decir, no es parcial pero aunque se indique no hay ningún error).
  • Dos ficheros con dos clases, ambas con la palabra clave Partial.
  • Dos ficheros con dos clases y sólo una de ellas con la palabra clave Partial.

Por otro lado, los métodos parciales son métodos donde su firma o prototipo está declarado en un fichero y su implementación está en otro fichero.

De nuevo y en tiempo de compilación, para aquellos métodos parciales para los que no se ha escrito una implementación, el compilador eliminará tanto el prototipo o firma del método, como todas las llamadas al mismo en nuestro código.

Un método parcial cumple las siguientes características:

  • Sólo se pueden declarar en clases parciales
  • Sólo pueden ser procedimientos (Sub)
  • Su ámbito tiene que ser privado
  • Sólo se usa la palabra Partial en el prototipo.
  • Los nombres de la implementación deben coincidir con los parámetros del prototipo.

Los usos más habituales de las clases parciales son:

  • Mejorar la legibilidad de clases muy grandes al separar la clase en varios ficheros.
  • Si se está trabajando con un software de control de código fuente, al separar la clase en varios ficheros se permite que varios desarrolladores trabajen en la misma clase y así evitar conflictos con la protección y desprotección de un solo fichero.
  • Con código auto-generado, el desarrollador puede escribir código personalizado para extender una clase en un fichero aparte con la seguridad de que no será machacado posteriormente si se vuelve a autogenerar el código.
  • También es posible separar conceptualmente los métodos de una clase (como si fueran regiones) o decidir que cuando se implementa una interfaz, ésta se implementa en un fichero aparte.

Por supuesto, y antes de que el ávido lector lo pregunte, una clase parcial no puede estar escrita en distintos lenguajes ni puede estar definida en distintos ensamblados, por lo que no se puede “anexar” una clase parcial a una clase de un ensamblado de terceros (para extender este tipo de clases podríamos utilizar los métodos extensores, pero esto será en otro post, que ya está escrito!)

Un error que suele suceder cuando hablamos de métodos parciales, es que se confunde un método parcial con un evento, y aunque tiene un parecido razonable, hay diferencias entre ellos que nos enseñan que no son conceptos intercambiables.

  • Un método parcial tiene que ser implementado en la propia clase, mientras que la suscripción a un evento puede ser realiza en cualquier clase.
  • La suscripción a un evento sucede siempre en tiempo de ejecución (siendo además posible anular esa suscripción, por ejemplo con RemoveHandler), mientras que con un método parcial el enlace es siempre en tiempo de compilación.
  • Un evento permite múltiples suscripciones y múltiples suscriptores.
  • Un evento permite distintos ámbitos de visibilidad (público, privado, etc.) mientras que un método parcial es siempre privado.

Hay que entender un método parcial como una “oportunidad” que, normalmente un código auto-generado, nos ofrece para personalizar su comportamiento. Con esto quiero decir que fuera del contexto de código autogenerado, un método parcial no parece tener mucho sentido (sobre todo porque el ámbito del método tiene que ser privado, así que un cliente de nuestra clase no podría hacer nada con este método).

No me gustaría finalizar este post sin algunos ejemplos que ilustrarán el uso de lo aquí expuesto:

' Clase parcial

Partial Public Class Persona

    Property Nombre As String

 

    Public Sub Saludar(ByVal saludo As String)

        ' Llamada a un método parcial

        ' Si durante la compilación, VS no encuentra una implementación

        '  para el método PrevioSaludar elíminará ésta llamada a PrevioSaludar

        PrevioSaludar(saludo)

        ' Fijarse que la propiedad Apellidos está en otro fichero

        Console.WriteLine(String.Format("Saludos {0} {1}", Nombre, Apellidos))

    End Sub

 

    ' Prototipo del método parcial PrevioSaludar

    ' NO puede tener código, sólo la firma

    Partial Private Sub PrevioSaludar(ByVal saludo As String)

    End Sub

 

End Class

 

' Clase parcial

Partial Class Persona

    Property Apellidos As String

End Class

 

Si ejecutamos ahora el siguiente código (y puesto que no hemos implementado el método parcial), la salida será la siguiente::

    Sub Main()

        Dim yo As New Persona With {.Nombre = "Sergio", .Apellidos = "León"}       

        yo.Saludar("Hola Mundo!")

        Console.ReadLine()

    End Sub

 

 

clip_image001

 

Sin embargo, si ahora implementamos el método parcial, tendremos ésta otra salida:

' Clase parcial

Partial Class Persona

    Property Apellidos As String

 

    ' Implementación de un método parcial

    ' Fijarse que NO lleva la palabra Partial

    ' Además, el nombre de los parámetros es igual que el prototipo

    Private Sub PrevioSaludar(ByVal saludo As String)

        Console.WriteLine(String.Format("Saludo parcial {0}", saludo))

    End Sub

End Class

 

clip_image002

Donde podemos ver que se ha llamado a la implementación del método parcial.

Un saludo!

viernes, 21 de enero de 2011

Cheatsheet

Escribir un post sobre qué es un cheatsheet parece un poco inservible, pero además de explicarte qué es una cheatsheet, también pretendo que sea un directorio de enlaces imperecedero donde volver cada cierto tiempo para encontrar este tipo de documento.

Un cheatsheet se traduce como hoja de trucos, de hecho cuando uno está jugando a un videojuego y aparentemente está haciendo trampa se le dice que es un “chetero”, luego que es un tipo que hace trampas. En cualquier caso, yo creo que la traducción más acertada sería una “chuleta” de toda la vida. Es decir, un pequeño documento de referencia para tener impreso junto a tu ordenador y de un vistazo localizar la funcionalidad deseada de un tema en concreto.

Este interés por las cheatsheets surgió cuando comencé a utilizar jQuery. Así, que ahí va la primera cheatsheet referente a jQuery http://woork.blogspot.com/2009/09/jquery-visual-cheat-sheet.html

Además, ahora me he bajado una cheatsheet de HTML5 http://woork.blogspot.com/2009/09/html-5-visual-cheat-sheet-by-woork.html

Una cheatsheet de Linq
http://www.aspnetresources.com/blog/linq_sqo__cheat_sheet.aspx

Otra cheatsheet muy interesante es sobre ASP.NET AJAX, http://weblogs.asp.net/scottgu/archive/2007/01/10/download-asp-net-ajax-pdf-cheat-sheets.aspx

Cheatsheet de CSS

http://www.smashingmagazine.com/2010/05/13/css-2-1-and-css-3-help-cheat-sheets-pdf/

Prometo ira actualizando este post a medida que vaya encontrando otras “chuletas” de interés manifiesto.

Un saludo!.

martes, 18 de enero de 2011

Anidar una aplicación ASP.NET dentro de otra

El otro día se me planteó el problema de publicar en un servidor de internet una aplicación dentro de una aplicación existente ya publicada en la raíz del mismo servidor. Es decir, imaginar que tenemos la aplicación “AplicacionRaiz” que es tan patética como 2 páginas .aspx con un diseño innovador (a través de un tema de ASP.NET) que establece el color de fondo en amarillo y el color de primer plano en azul.  Todo parece ir bien (excepto algunos usuarios que comienzan a sufrir ataques epilépticos después de navegar por nuestra aplicación) pero después tengo la necesidad de publicar “AplicacionAnidada” dentro de “AplicacionRaiz”, aun cuando “AplicacionAnidada” no tiene nada que ver con “AplicacionRaiz”.

Vemos primero lo bonita que es “AplicacionRaiz” ya publicada en nuestro servidor de internet.

clip_image001

Después nos ponemos a programar “AplicacionAnidada” y como el diseño anterior no causo mucho furor entre los usuarios, pensamos que mejor lo dejamos sin estilo y que un blanco nuclear llene de emoción nuestra vida.

clip_image002

Ahora publicamos nuestra “AplicacionAnidada” en el servidor web de producción dentro de la “AplicacionRaiz”, la cual no podemos esquivar puesto que está publicada en la raíz del web, C:\inetpub\wwwroot\.

Ahora exploramos “AplicacionAnidada” en el servidor web y vemos que pasa algo extraño.

clip_image004

Upss!, en “AplicacionAnidada” no recuerdo haber establecido ningún tema, de hecho no lo hice porque soy un pésimo diseñador, así que todo apunta a que “AplicacionAnidada” está heredando la configuración de “AplicacionRaiz”. Vamos, lo confirmo porque en la pantalla de error aparece como archivo de origen el fichero web.config de “AplicacionRaiz”. Pues bien, dicho esto tenemos una solución fantástica para decirle a “AplicacionAnidada” que NO herede nada de “AplicacionRaiz”, de hecho queremos que “AplicacionAnidada” sea una aplicación completamente distinta de “AplicacionRaiz”… de hecho lo son!

La solución pasa por decir en la aplicación padre (en nuestro caso “AplicacionRaiz”) que no propague su configuración a aplicaciones hijas, en nuestro “AplicacionAnidada”). Esto se consigue a través de la propiedad inheritInChildApplications del elemento location del fichero web.config.

El truco está en crear una sección location con path = “.” y con inheritChildApplications = “false” y meter dentro de esta localización el resto del fichero web.config (bueno todo no, porque la sección configSections y runtime tienen que estar fuera).

Por ejemplo:

<location path="." inheritInChildApplications="false">
El resto de tu fichero web.config iría aquí…
</ location>

Ahora al navegar a “AplicacionAnidada” ya volveremos a ver nuestro bonito blanco nuclear ;-)

clip_image005

Un saludo!.

 

Snippet Designer

En una entrada anterior, “Mis extensiones favoritas”, mencioné el complemento Snippet Designer , http://snippetdesigner.codeplex.com/. En este post, trataremos sobre cómo crear snippets con este plug-in y sobre cómo sacarle el máximo provecho.

Para instalarlo basta con ir al menú Herramientas > Administrador de extensiones… y localizarlo por ejemplo con la palabra snippet en el cuadro de búsqueda.

clip_image002

Para crear un snippet, tendremos que seleccionar el código en el editor de VS y en el menú contextual, seleccionar la opción “Export as Snippet”.

Para nuestro ejemplo crearemos un snippet que saluda al basto mundo que nos rodea… vale, es una chorrada, pero para ilustrar como crear un snippet y configurarlo es suficiente.

Nuestro código es el siguiente:

clip_image003

Así, nuestro siguiente paso será seleccionar el texto y pulsar “Export as Snippet” en el menú contextual.

clip_image004

Después de esto aparentemente no pasa nada y aún no está disponible nuestro snippet. Para terminar de completar la operación, tenemos que pulsar el menú Archivo > Nuevo > Archivo… y seleccionar un archivo de tipo “Code Snippet” en la categoría “Snippet Designer”.

clip_image006

Automáticamente se abrirá un nuevo archivo con el código que exportamos anteriormente.

clip_image008

Además, en cuanto a la configuración del snippet es muy importante la ventana propiedades que expone las principales características del snippet.

clip_image010

Antes de configurar el código de nuestro snippet (para que admite variables de reemplazo), configuraremos el snippet en lo relativo a la ventana de propiedades.

·        File Path muestra el fichero temporal donde se creó el snippet cuando pulsamos “Export as Snippet”.

·        Author y Description son informativos.

·        Help Url.

·        Imports es una colección de instrucciones Import que agregará el snippet.

·        Keywords es una lista de palabras clave para la posterior localización del snippet en la nueva ventana que incorpora el Snippet Designer.

·        References es una colección de referencias que agregará automáticamente el snippet.

·        Shorcut será el atajo por el que llamaremos a nuestro snippet. Es importante señalar que no debe contener espacios.

·        Snippet Kind. Puede ser MethodBody, MethodDecl, TypeDecl.

·        Snippet Type. Puede ser Expansion o SurroundsWith.

En nuestro ejemplo, hemos configurado nuestro snippet de saludo de la siguiente forma:

Author

Sergio León

Description

Saludo básico en Visual Basic

Help Url

http://panicoenlaxbox.blogspot.com

Imports

System.Web.UI.WebControls

Keywords

Saludo

References

System.Web

Shortcut

misaludo

Snippet Kind

MethodBody

Snippet Type

Expansion

 

Otra cosa a tener en cuenta es el que es necesario dar un nombre al snippet en la caja que aparecer en la parte superior del editor. Nosotros lo llamaremos miprimersnippet. De hecho, al guardar el documento, se propone este nombre como nombre del fichero .xml donde se va a guardar el snippet.

clip_image012

Pues bien, al pulsar Guardar habrá acabado nuestro trabajo y ya tendremos nuestro snippet disponible.

clip_image014

Como vemos nos informa que el acceso directo es “misaludo” (propiedad Shortcut), que su descripción es “Saludo básico en Visual Basic” (propiedad Description) y que el snippet se llama “miprimersnippet

También podemos ver nuestro snippet recién creado en el menú Herramientas > Administrador de fragmentos de código

clip_image015

Como vemos, aquí también nos informa del tipo del snippet (propiedad Snippet Type, en nuestro caso Expansion) y del Autor (propiedad Author).

Además, el plug-in Snippet Designer ha agregado a VS una nueva ventana accesible desde el menú Ver > Otras ventanas > Snippet Explorer

clip_image016

Como vemos desde esta nueva ventana podemos buscar por las palabras clave que especificamos anteriormente (propiedad Keywords). Además de ver el código, también podemos abrir el snippet para editarlo de nuevo o bien eliminarlo.

Antes de continuar con la edición del snippet quisiera explicar la propiedad Snippet Type.

Snippet Type puede ser Expansion o SurroundWith. Surround significa rodear. De este modo, esta propiedad nos indica cómo se va insertar nuestro snippet en el código.  Expansion significa que nuestro snippet se insertará donde esté colocado el cursor, mientras que SurroundWith coloca el snippet alrededor de una parte de código seleccionada.

Si editamos el fichero .xml que guarda el snippet veremos que tiene el siguiente código que es bastante autoexplicativo.

<?xml version="1.0" encoding="utf-8"?>

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">

  <CodeSnippet Format="1.0.0">

    <Header>

      <Keywords>

        <Keyword>Saludo</Keyword>

        <Keyword>Mundo</Keyword>

      </Keywords>

      <SnippetTypes>

        <SnippetType>Expansion</SnippetType>

      </SnippetTypes>

      <Title>miprimersnippet</Title>

      <Author>Sergio León</Author>

      <Description>Saludo básico en Visual Basic</Description>

      <HelpUrl>http://panicoenlaxbox.blogspot.com</HelpUrl>

      <Shortcut>misaludo</Shortcut>

    </Header>

    <Snippet>

      <References>

        <Reference>

          <Assembly>System.Web</Assembly>

        </Reference>

      </References>

      <Imports>

        <Import>

          <Namespace>System.Web.UI.WebControls</Namespace>

        </Import>

      </Imports>

      <Code Language="vb" Kind="method body"><![CDATA[        Dim saludo As String

        saludo = "Hola Mundo!"

        Console.WriteLine(saludo)

        Console.ReadLine()]]></Code>

    </Snippet>

  </CodeSnippet>

</CodeSnippets>

Una de las características que me maravilla de los snippets son las variables de reemplazo. Pues bien, ha llegado el momento de ver cómo crear estas variables con Snippet Designer.

Basta con escribir algo que tenga el formato $literal$ y se agregará automáticamente una variable de reemplazo. Yo por mi parte he cambiado los valores predeterminados que agrega automáticamente Snippet Designer (como Tooltip, Defaults to…) para ver cómo se comporta después en ejecución.

clip_image018

Ahora insertaremos de nuevo el snippet en nuestro módulo de código:

clip_image019

Como vemos ahora nuestro snippet es mejor y más utilizable y además la propiedad Tooltip y Defaults to han funcionado… bien!

Si volvemos a ver el fichero .xml ahora ha agregado la sección Declarations y ha cambiado la sección Code.

      <Declarations>

        <Literal Editable="true">

          <ID>tusaludo</ID>

          <ToolTip>Tu saludo</ToolTip>

          <Default>Tu saludo va aquí</Default>

          <Function>

          </Function>

        </Literal>

      </Declarations>

      <Code Language="vb" Kind="method body"><![CDATA[        Dim saludo As String

        saludo = "$tusaludo$"

        Console.WriteLine(saludo)

        Console.ReadLine()]]></Code>

Si quieres el manual oficial del complemento, aunque el mío es mejor, te aviso ;-), está en este dirección http://snippetdesigner.codeplex.com/wikipage?title=createFromScratch&referringTitle=Documentation

Un saludo y a snipear se ha dicho!.