Nota del autor

Si la entrada que estás leyendo carece de imágenes, no se ve el vídeo que teóricamente lleva incrustado o el código fuente mostrado aparece sin formato, podéis conocer los motivos aquí. Poco a poco iré restableciendo la normalidad en el blog.
Este blog es un archivo de los artículos situados previamente en Lobosoft.es y ha dejado de ser actualizado. Las nuevas entradas pueden encontrarse en www.lobosoft.es. Un saludo,
Lobosoft.

lunes, 18 de febrero de 2008

Métodos de extensión en .Net Framework 3.5

Entre las numerosas novedades que atesora la nueva versión del framework de desarrollo de Microsoft se encuentra la que han dado en llamar "métodos de extensión" o "extension methods", que no son más que una forma de proporcionar funcionalidad a clases en las que no podemos hacerlo mediante herencia convencional, como ocurre, por ejemplo, con las clases selladas.


Por ejemplo, imaginemos que necesitamos un método para que, dada una determinada cadena de caracteres, genere un código HTML válido a partir de la entrada. Es decir, que sustituya los caracteres acentuados y especiales por sus equivalentes (por ejemplo, "Á" por "&Acute;", "ñ" por "ñ", etcétera). Dado que la clase String no permite la herencia, una opción hasta ahora habría sido crear una clase de utilidades donde incluir el método que implementase la nueva funcionalidad que necesitamos. Sin embargo, esto es poco intuitivo, y un programador que llegase al proyecto donde usamos este método no tendría porqué saber que existe una clase "MisUtilidadesDeTexto", por ejemplo, donde se implemente este método. Ni tan siquiera un IDE como Visual Studio sería capaz de mostrar ese método relacionado con la clase String. La idea que subyace tras todo esto es tener un método al que llamar en la forma


string str = mitexto.ToHTML();


que funcionase así de forma similar a mitexto.ToLower(), por poner un ejemplo.


Una posible solución a esto es la que propone Microsoft en su .Net Framework 3.5 mediante el uso de los métodos de extensión. Básicamente, estos métodos permiten ampliar la funcionalidad de una clase sin hacer uso de la herencia. Sí, es algo para tirarse de los pelos, lo admito, y que echa por la borda buena parte del paradigma de la programación orientada a objetos. Sin embargo, tras haberlo usado un poco, he de coincidir en que es una herramienta que ahorra bastante trabajo en determinadas ocasiones, aunque hay que andarse con mucho cuidado para no abusar de ella.


La forma de implementar y usar un método de expansión resulta francamente sencilla. Basta con definir una clase estática que implemente los métodos de extensión que necesitemos. En la definición del método, la única restricción es que el primer parámetro debe ser declarado del tipo de la clase que deseamos "enriquecer" y usando el modificador this.



[csharp]
public static class HtmlStringUtils
{
public static string ValidHtmlChar(this string s)
{
foreach (KeyValuePair kvp in diccionarioHTML)
{
s = s.Replace(kvp.Key,kvp.Value);
}
return s;
}
}
[/csharp]

Ahora, simplemente, podemos llamar a dicho método desde las clases principales de nuestra solución, e IntelliSense nos mostrará información sobre el mismo, entre otra, que se trata de un método de extensión.



IntelliSense con métodos extendidos


Si deseamos definir métodos con más parámetros, lo único que hemos de tener en cuenta es que el primero debe definirse tal y como se indicaba anteriormente. Por ejemplo, un método que encierre nuestro texto dentro de una determinada etiqueta HTML podría ser el siguiente:



[csharp]
public static string AplicarEtiqueta(this string s, string etiqueta)
{
return "" + s + "";
}
[/csharp]

y la llamada correspondiente podría ser algo como


string miHtml = "Hola mundo en " + "negrita".AplicarEtiqueta("STRONG");


que devolvería el HTML Hola mundo ennegrita correspondiente a la presentación "Hola mundo en negrita".


Hasta aquí todo perfecto. Sin embargo, existe una serie de problemas subyacentes, como la dependencia de los métodos de extensión de la clase que extienden, y que una posible evolución de esta los deje en estados inconsistentes o erróneos o, simplemente, que pierdan su funcionalidad.


Otra cuestión que hemos de considerar es la posibilidad de que futuras implementaciones de la clase incluyan métodos de igual nombre y parámetros, que provocarían que los de la instancia prevaleciesen sobre los de extensión, de manera que éstos no llegaran a ejecutarse ya que, por seguridad, siempre se ejecutará antes un método de instancia evitando así el posible "secuestro" de nombres de métodos.


Otro posible error podría derivarse de la definición de dos métodos de extensión de igual nombre pero ubicados en distintos espacios de nombres, por lo que la ejecución de uno u otro sólo dependería del que referenciásemos mediante using en nuestro código.


Por tanto, y resumiendo, nos encontramos ante un aspecto más que deberemos considerar en el desarrollo con el .Net 3.5, pero que no convendrá descuidar si optamos por incluirlo finalmente en nuestros proyectos.

No hay comentarios:

Publicar un comentario