December 2006 - Artículos - miguel jimenez en español // MVP C#

December 2006 - Artículos

Para aquellos que no esten al tanto de esta historía, Microsoft y AMD han decidido regalar 2000 portatiles Ferrari de gama alta precargados con Windows Vista a bloggers e influenciadores, algunos incluso un Media Center. Gratis. Debe molar si eres uno de los bloggers seleccionados. Pero rapidamente ha empezado a chirriar y rugir por la blogoesfera, tan pronto como se anuncio.

Algunos piensan que se merecían un portatil gratis, mientras otros ni siquiera dijeron que fue un regalo de Microsoft. Algunos más comenzaron a hablar sobre Microsoft comprando opiniones sobre Vista, y lectores empezarón a atacar a bloggers acusuandoles de no ser objetivos en sus opiniones porque habian sido "comprados" por Microsoft.

Guauuu! Esto esta totalmente fuera de sus casillas.

Microsoft siempre ha obsequiado a colaboradores e influenciadores, sino echad un vistazo a los programas de MVP o Regional Directors. Mucha gente participó en el programa Beta de Windows Vista, y se esponsorizarón licencias gratuitas para algunos de los que más bugs habian reportado. No es cuestión de comprar buenas opiniones. Es más bien cuestión de proporcionar un entorno de pruebas donde obtener la mejor experiencia de Vista de forma que te puedas expresar libremente acerca de la experiencia de usuario real. Por supuesto, si you tuviese que elegir gente para que evaluase Vista de la mejor forma posible, los elegidos serían las personas más influyentes de la comundidad en Windows Vista.

Pienso que toda esta historia no es demasiado importante o relevante como para llegar a estos extremos... parece más como un poco de pelusa de todos aquellos que no han recibido un portatil (y yo no lo he recibido, que conste)... no creo que alguien cambien su objetividad por esto, o dejarias que tu ética se balancease por un regalo de este tipo?

Personalmente, mi ética u objetividad nunca se ha visto afectada, ni cuando he hablado en eventos de Microsoft, blogeado sobre sus productos, escrito sobre sus bugs, productividad o cualquier otro tema relacionado... Creo que el punto principal que Microsoft busca cuando crea comunidad es encontrar gente que sea capaz de hablar coherentemente de la experiencia con sus productos, no alguien a quien se pueda comprar con un regalo.

Publicado 29/12/2006 16:28 por Miguel Jimenez | 1 comment(s)
Archivado en:

El próximo año esta comenzado con un mes realmente activo. Esta es la lista de eventos que tengo programados, así que si vives en alguna de las ciudades que visitaré (o alrededores) y estas interesado en charlar un rato, no dudes en contactar conmigo para tomar unas cañas ;) También estoy interesado en conocer a gente en Tenerife que desee unirse a INETA y formar un grupo de usuarios de .NET en aquellas tierras...

Actualmente, los eventos programados son:

  • C# 3.0 Language Features // Madrid .NET User Group, 18 de Enero de 2007

Introducción de Extension Methods, Query Languages, Lambda Expressions y las nuevas novedades de lenguaje de C# 3.0. Más detalles y registro en http://www.madriddotnet.com

  • C# 3.0 Language Features // .NET User Group Galicia, Coruña, January, 19th 2007

Primera reunion del .NET User Group Galicia, y yo estaré por allí presentando Extension Methods, Query Languages, Lambda Expressions y resto de novedades de lenguaje para C# 3.0. Más detalles y registro en http://www.nugg.es

  • LOVE Tour: Windows Workflow and Windows Communication Foundation // Tenerife, 23 de Enero de 2007

Sigo colaborando con MSDN presentando el .NET Framework 3.0 en las principales ciudades de España. Esta vez estaré en Tenerife (Islas Canarias) presentando Windows Workflow y Windows Communication Foundation. Más detalles y registro en http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032312578&Culture=es-ES

  • LOVE Tour: Windows Presentation Foundation // Málaga, 25 de Enero de 2007

Sigo colaborando con MSDN presentando el .NET Framework 3.0 en las principales ciudades de España. Esta vez estare en Málaga, directamente desde Tenerife, presentando las mejoras en interfaz de usuario de Windows Presentation Foundation. Más detalles y registro en http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032312580&Culture=es-ES

Y para Febrero, más!!

Publicado 28/12/2006 14:30 por Miguel Jimenez | con no comments
Archivado en: ,,,,

Hace un par de dias mi amigo Ricardo Varela comenzo a bloggear en español (en paralelo con su actual blog en inglés). Miembro activo de comunidades Microsoft, trabaja actualmente en Google UK. Pero lo relevante es que en su nuevo blog ha comenzado con un post con algo de acertijos de programación, volviendo a lo básico, a los principios del desarrollo. Esto va a ser divertido.

Bein, esta es mi respuesta a su post. Habia tres preguntas relacionadas con estructuras de datos y modos de pensar alternativos sobre como dar la vuelta a las cosas.

 

  • Sabes dar la vuelta a una cadena de texto? Por ejemplo, si tienes "abc" la cadena de retorno debería ser "cba"

Esto parecía bastante sencillo. En C# cadena se representa como un array de caracteres, por tanto puedes usar el indexador para obtener el caracter de una posición y darles la vuelta "manualmente" con algo como:

string inputString = "abc"; string reversedString = string.Empty; for (int c = inputString.Length; c > 0; c--) { reversedString += inputString[c - 1]; } Console.WriteLine("Original String: " + inputString); Console.WriteLine("Reversed String: " + reversedString);

O puedes usar la funcionalidad del framework de .NET para hacerlo de manera mas "elegante":

char[] chars = inputString.ToCharArray(); Array.Reverse(chars); // Use the reversed array of chars
  • Un poco más profundo en estructuras de datos,  sabrías dar la vuela a los bits de un byte? Por ejemplo, si tenemos 1 el byte de retorno debería ser 128

Debo admitir que esta ha sido dificil. Aunque tengo perfectamente claro los conceptos de bits, bytes y operaciones bitwise, el lenguaje C# no ofrece una manera sencilla y estructurada de acceder a esos elementos fundamentales de las estructuras de datos. Finalmente consegui hacerlo. La estructura de datos más pequeña disponible para representar el interior de un byte que he encontrado es un simple byteMusic, así que solo queda rellenarlo coon los valroes para cada byte:

static byte[] getBits(byte inputByte) { byte[] bits = new byte[8]; for (int p = 0; p < 8; p++) { bits[7 - p] = (byte)(1 & (inputByte >> p)); } return bits; }

Sencillo? Vale, lo explico un poco... el operador bitwise >> simplemente desplaza los bits del byte hacia la derecha, así que si desplazamos 01010101 una posición a la derecha obtenemos 00101010... después una simple operacion AND logica con la máscara 00000001 para determinar si el bit esta marcado. Almaceno el estado de cada bit en el array de salida y lo devuelvo. Como nota rápida, el array de bits se puede obtener dado la vuelta directamente si cambio la linea dentro del bucle for a:

bits[p] = (byte)(1 & (inputByte >> p));

Pero unos métodos genericos para convertir entre byte y bits suena un poco mejor, así que no lo he incluido directamente en ese método. Una vez que tenemos el array, es sencillo darle la vuelta con los métodos mostrados anteriormente para las cadenas:

Array.Reverse(bits);

Y ahora, solo tenemos que ser capaces de convertir el array de bits de vuela a un byte:

static byte setBits(byte[] bits) { byte obyte = bits[0]; for (int p = 1; p < 8; p++) { obyte = (byte)((obyte << 1) + bits[p]); } return obyte; }

El método es similar al usado para extraer los bits, pero esta vez el operador bitwise << desplaza los bits a la izquierda, de forma que puedo incrementar el número hasta que alcanza el valor marcado. Un sencillo programa para probar como funciona podria ser:

byte inputByte = 1; byte outputByte = 0; byte[] bits = getBits(inputByte); Array.Reverse(bits); outputByte = setBits(bits); Console.WriteLine("Input Byte: " + inputByte); Console.WriteLine("Reversed Byte: " + outputByte);
  • Y la más compleja. Los números de coma flotante se representan habitualmente con el estándar IEEE 754, serías capaz de dar la vuela a los bits de un numero en coma flotante? Por ejemplo, si tenemos 118.625f la salida debería ser -17180580000f

Wow! Esta era realmente complicada. No conocia el funcionamiento del estandar IEEE 754 así que me lo he leído en la wikipedia (la página de este estandar en el IEEE está en revisión y no había información disponible) y parece que es relativamente sencillo. La representación en coma flotate es una estructura de datos de 32bits con la siguiente información: 

Ahora me parece algo más sencillo. Simplemente hemos de dar la vuelta a los bits, en C# los dos tipos de coma flotante son float y double, el primero para almacenar con precisión de 32bits y el segundo con 64bits; el problema es que estos tipos no permiten operaciones bitwise, y necesito crear algun método nuevo basado en la clase BitConverter.

Es probable que esto se pueda refactorizar para que solo un par de métodos resuelvan todas las necesidades de operaciones con bits, pero el objetivo era dar la vuelta a un numero en coma flotante, así que alla vamos:

static byte[] getFloatingBits(double input) { byte[] bytes = BitConverter.GetBytes(input); if (BitConverter.IsLittleEndian) { Array.Reverse(bytes); } byte[] bits = new byte[64]; for (int i = 0; i < 8; i++) { Array.Copy(getBits(bytesIdea), 0, bits, i * 8, 8); } return bits; }

Explico el método un poco... El tipo float se puede dividir en 4 bytes y el método BitConverter.GetBytes nos da un array de esos bytes, pero desafortunadamente no incluye un método que nos permita reconvertir dicho array en un float, así que uso el tipo double y casting :(

La lógica es muy sencilla, extraemos los 8 bytes de la doble precisión de coma flotante. Despues, verificamos si el procesador es LittleEndian y en ese caso damos la vuelta a los bytes para reflejar el verdadero valor. Copiamos todo a un array de bits, y ya estamos. Ahora solo nos queda dar la vuelta al array de bits:

Array.Reverse(bits);

Y volver al método que nos permite invertir el proceso para obtener un número de coma flotante a partir de un array de bits:

static double setFloatingBits(byte[] bits) { byte[] bytes = new byte[8]; for (int i = 0; i < 8; i++) { byte[] actualByte = new byte[8]; Array.Copy(bits, i * 8, actualByte, 0, 8); bytesIdea = setBits(actualByte); } if (BitConverter.IsLittleEndian) { Array.Reverse(bytes); } return BitConverter.ToDouble(bytes, 0); }

El problema es que el número esperado no coincide con el resultado obtenido con este método para dar la vuelta al array de bits completo. De hecho, he releido la pregunta y dice "eres capaz de dar la vuelta al orden de bits de exponente y mantisa?" ... He hecho exactamente eso también, cambiar los bits solo de mantisa y exponente, obteniendo los siguientes arrays de bits:

Original: 0 10000000 10111011010100000000000 Reversed: 0 00000001 00000000000101011011101 Expected: 1 10000100 00100000000000000101011

Pero el numero que hemos dado la vuelta no representa el que Ricardo indicaba en su post. Que estoy haciendo mal? Hay algo mal en mi modo de afrontar el problema o el número experado es inncorrecto? Tengo bastante curiosidad sobre porque hay un bit menos (como 1) en el numero esperado y como se ha cambiado el signo.

Este año esta dando sus ultimos coletazos. Para mi ha sido un año divertido y activo, tanto personal como profesionalmente. Espero que hayais conseguido lo que esperabais de él.

Os deseo una feliz navidad y que empeceis el próximo 2007 llenos de energía y logros.

Pasadlo bien estas vacaciones!!

Publicado 25/12/2006 20:50 por Miguel Jimenez | con no comments
Archivado en:

Por fin se ha publicado. Ayer. Así que si instalaste el Service Pack 1 de Visual Studio 2005 en una máquina con Windows Vista ya puedes eliminar ese molesto popup que salta en tu cara cada vez que inicias el IDE. Este parche pretende minimizar el impacto de los "problemas" de ejecutar Visual Studio 2005 sobre Windows Vista.

Corre, ve y descargalo de http://www.microsoft.com/downloads/details.aspx?FamilyID=fb6bb56a-10b7-4c05-b81c-5863284503cf&DisplayLang=en

Yo ya lo he descargado e instalado. Y la verdad, estoy deseando ver las mejoras que ha incluido en mi Visual Studio 2005 y sobre todo en Team Explorer, Team System y Team Foundation Server (que también han sido agraciados con este service pack)

Ayer por la tarde decidi salir y pillarme una Xbox 360. Era un poco reticente de comprar esta consola porque soy un fan aferrimo de PS2 a consecuencia de la serie Final Fantasy. De cualquier forma, ahroa estoy empezando con la 360, pero actualmente solo tengo un juego: Splinter Cell Double Agent.

Cosas que me han encantado de mi primera eXperiencia: el interfaz de usuario, las opciones de Xbox live, las capacidades de media center y la forma en que mi Vista Ultimate detecto la 360 y la configuró como extensión. También me encanta la posibilidad de crear cosas con XNA desde mi ordenador y poder ejecutarlas en la X; veremos si esto resulta ser una buena idea ;)

Cosas que no me gustaron tanto: hay algun motivo especial para que la fuente de alimentación sea externa y tan tan grande??

Si también estas en el lado 360 de la vida, juguemos un rato a algo. Mi gamertag es:

Migs212

 

PD: Sunday Geek es una categoría en la que postear las cosas que alguienunpocogeek hace un Domingo típico.

Estaba leyendo un post de Perci Reyes, inspirado en un post sobre como comprender el código en Coding Horror. Después de leerlo, junto a todos los articulos relacionados (lo que piensa Joel y el post de Peter Hallam), creo que tengo algo que añadir y que parece no importar a nadie...

En primer lugar, estoy deacuerdo con los autores sobre las estadisticas presentadas de las actividades de un desarrollador... y quizás sea cierto que empleamos mucho tiempo en comprender código existente. Por defecto, los programadores somos tan narcisistas que necesitamos sentir que hemos creado algo, y somos propensos a cambiar cualquier cosas que no comprendamos a una solución más apropiada y personal, siempre bajo nuestro punto de vista. Todo el mundo parece discutir acerca de este narcisismo y los programadores deseando reescribir código en lugar de comprenderlo, pero yo tengo algunas dudas sobre si es un problema de los desarrolladores o del código en sí...

Es decir, es el código demasiado complejo para comprenderlo? Puede que lo sea. Personalmente he visto miles de lineas de código imposibles de seguir y comprender porque la arquitectura elegida, las capas de negocio o datos, el modelo de presentación o incluso la capa de UI no estaban diseñadas de manera correcta o ni siquiera existian. Esto añade mucha complejidad, pero debeis admitir que no esta relacionado con el desarrollador que modifica ese código. Es el propio código. Ese código fue escrito por un desarrollador que lo pensó como la mejor solución a un problema de negocio (o quizás era la mejor solución posible que podia implementarse con determinadas restricciones del proyecto, solución o el propio desarrollador; o quizás debido a una falta de experiencia o conocimiento del desarrollador que escribió el código)

Supongo que un equipo de desarrollo que trabaja en una solución lo hace de la mejor manera posible, usando patrones conocidos, desacoplando el código e interfaz de usuario, y refactorizando clases y métodos. Siguiendo algunas sencillas reglas deberiamos ser capaces de no encontrar cosas como un metodo con 400 líneas o una clase con un único método de 2000 líneas de código. Y prometo que este tipo de código existe, lo he visto muchas veces.

En ese caso, yo probablemente cambiaría y reescribiría el código que "huele". No porque lo prefiera hecho por mí, sino porque esta falta de diseño nos conduce a la locura y descontrol durante el desarrollo; pero lo más importante, sino se corrige frustrará el trabajo de futuros desarrolladores que tengan que mantenerlo o extenderlo.

Mi opinión acerca del hilo de posts es que simplemente hay que tener en cuenta que los desarrolladores somos narcisistas pero también somos capaces de leer código que sea comprensible. El problema para mi es la introducción de software mal diseñado, que desgraciadamente se puede encontrar por todos lados. Necesitamos tener en mente que cualquier pieza de código que desarrollemos se pondrá en producción en algún momento, y será mantenida o soportada por un equipo de desarrolladores (probablemente distinto al que lo desarrollo) que necesitará comprenderla.

Mi consejo personal es (y esto es lo que yo hago cuando escribo código en cualquier proyecto) que cada desarrollador ahí fuera debería escribir codigo de la mejor forma posible pero siempre haciendolo perfectamente legible y comprensible. El código debe hablar por sí mismo, no a través de comentarios añadidos para comprenderlo, y debe ser refactorizado y simplificado hasta que sea legible por simples humanos. No es tan dificil. Hay muchas prácticas que permiten conseguir este objetivo y además, bajo mi punto de vista, hacernos mejores desarrolladores; pero mi frase favorita es:

"si sientes la necesidad de añadir un comentario, simplemente refactorizalo para que el comentario sea supérfluo. de esta forma tu código será más simple y facil de comprender"

Simplemente una nota rápida para destacar el primer evento de Artalde, el recientemente creado grupo de usuarios de .NET de Bilbao. El evento tendrá lugar este Miercoles, 13 de Diciembre en la Universidad de Deusto. Participaré en el evento, junto a Oscar Alvarez de Ibermática, hablando sobre Windows Communication Foundation.

Si esta por la zona, no dudes en pasarte y charlar un rato con nosotros.

Visita la pagina de registro del evento en MSDN Events

 

Por cierto... este miercoles va a ser un día movidito en la escena de grupos españoles, porque la gente de NavarraDotNet, el también reciente grupod de usuarios dde .NET de Pamplona, celebran su primer evento público con Chema Alonso de Informatica64 hablando sobre Desarrolladores y Seguridad. Visita la pagina de resgistro en MSDN Events

Publicado 11/12/2006 11:24 por Miguel Jimenez | 1 comment(s)
Archivado en: ,,

Mucha gente me pregunta sobre el porcentaje que aparece en el nickname de mi messenger. Algunos incluso piensan que es el estado de completitud de cualquiera de los proyectos en los que estoy involucrado, e incluso se preguntan como seré capaz de medirlo tan precisamente.

De hecho, este porcentaje (actualmente el 63,78%) no esta relacionado con la tecnología, sino con la naturaleza. Es el nivel de agua de los pantanos y embalses de Madrid. He estado monitorizandolo durante las ultimas 5 o 6 semanas. Diariamente. Voy a la página del distribuidor de agua y lo compruebo manualmente. Realmente me ha sorprendido como hemos pasado de un triste 27% a los indices actuales en periodo tan corto de tiempo. Impresionante. Y por supuesto, bienvenido!

Pero esta tarea es aburrida. Muy aburrida. Lo queria directamente en mi escritorio. Por tanto, este parece un escenari perfecto para que el Inspector Gadget juegue con Windows Vista!!!

Primero necesitamos una pagina Html sencilla que albergue el código de nuestro gadget. Es simplemente javascript + html, también conocido como el famoso dhtml. Después necesitamos un iconoito que poner en la librería de Gadgets y por supuesto una buena cantidad de intervalos de javascript, json, webservices, xml y parsers de xsl para obtener los datos.

Consegui acceso a un servicio web que proporciona el nivel de agua embalsada de Madrid y escribí el código para incrustarlo en un gadget, lo arrastre a mi Sidebar y voilá! ya esta haciendo el trabajo sucio por mi.

Si sientes curiosidad sobre como esta hecho, descarga el Agua Gadget e inspecciona el código. Aún es muy sencillo. Tengo intención de actualizarlo para que soporte settings, unos gráficos mejores y que sea capaz de monitorizar más areas de España (mi conocimiento actual acerca de la distribución de agua esta limitado a España, pero si conoces alguan fuente de datos en tu región, no dudes en contactar conmigo y estaré encantado de añadirla)

Descarga Agua Gadget 0.1 para Windows Vista. Para instalarlo, simplemente descomprime el zip y haz doble click sobre el fichero .gadget y Windows Vista lo instalará por ti :)

Puedes encontrar mas información sobre la creación de gadgets en este tutorial paso a paso y más info aún en la referencia online del System.Gadget namespace.

En el siguiente post voy a explicar un patrón muy usado en el desarrollo de software y como encaja en el ecosistema del .NET Framework. Este patrón puede ser catalogado, probablemente, en la categoría de estructurales y se usa principalmente para desacoplar componentes de forma que abstracciones e implementaciones puedan variar independientemente.

Usar el patrón proveedor en .NET (y en la mayoría de lenguajes orientados a objetos) es muy sencillo. Necesitamos los siguientes elementos:

  • Una definición del proveedor, usada como un contrato que especifíca que se puede hacer
  • Una o varias implementaciones del proveedor declarado
  • Un consumidor que desea hacer uso del proveedor

Imaginad el siguiente escenario: Existe una definición básica de lo que debe hacer un coche (definición de proveedor) y lo que es considerado como tal: tiene que tener 4 ruedas, un volante, etc... en el mercado, es posible encontrar varias implementaciones que concuerdan con la definición de coche (implementaciones del proveedor), y nosotros, como consumidores, podemos usar la definición del proveedor (coche) para cambiar la implementación sin afectar al comportamiento (somos capaces de conducir cualquier coche, de cualquier marca, porque todos usan la misma definción de contrato, el mismo interfaz: volante, acelerador, ruedas, etc...).

Ahora imaginemoslo en el contexto del desarrollo de software. Tenemos un interfaz que define un conjunto de propiedades y métodos que nuestros proveedores deben implementar; después tenemos una o varias implementaciones de ese interfaz; y, por supuesto, una aplicación o servicio que los consume puede usar el interfaz para seleccionar la implementación a usar sin que afecte a su comportamiento. Echad un vistazo al siguiente diagrama que explica como funciona este patrón:

Es bastante impresionante, práctico y sencillo cuando desseamos crear aplicaciones desacopladas y componentizadas. Simplemente usamos interfaces. Orientación a objetos. Este patrón se ha usado muchisimo en la implementación de ASP.NET 2.0, sobre todo en la creación de los servicios de aplicación. Por ejemplo, el MembershipProvider (contrato o definíción del proveedor) puede ser bien un SqlMembershipProvider o un proveedor propio OracleMembershipProvider (implementaciones concretas del proveedor), ambos proveen la misma funcionalidad (especificada en el contrato del proveedor) pero con diferente comportamiento (uno utiliza SQL Server como repositorio de datos mientras el otro utiliza bases de datos de Oracle).

Este patrón de diseño es capaz por si solo, bajo mi honesta opinión, de incrementar dramaticamente la calidad de practicamente cualquier arquitectura de software actual, basicamente por la modularidad y simplicidad de desarrollo, despliegue y configuración que propociona.

Uno de los grandes y ocultos tesoros del .NET Framework 2.0 es la existencia de un framework del patrón proveedor, Provider Model, que permite crear proveedores personalizados para cualquier tarea (no solo para extender los proveedores de ASP.NET como Membership o Roles, sino para cualquier aplicación y servicio desarrollado en .NET)

 

Usando el Provider Model de .NET Framework 2.0

Bueno, empezemos a  ver algo de código. Para crear nuestro proveedor primero tenemos que crear un clase abstracta que defina nuestro contrato. Esta clase tiene que implementar la clase abstracta System.Configuration.ProviderBase y debe contener la definición de métodos y propiedades usadas como "contrato" de nuestro proveedor.

public abstract class ImageProvider : ProviderBase { public abstract bool CanSaveImages { get; } public abstract Image GetImage(int id); public abstract void SaveImage(Image image); }

Despues necesitamos incluir la implementación del proveedor. En este caso, añadiremos un proveedor de imagenes que sea capaz de gestionarlas en el sistema de archivos (disco) y además añadiremos otro proveedor que se capaz de gestionarlas en Sql Server.

public class FileSystemImageProvider : ImageProvider { public override bool CanSaveImages { get { return true; // As we allow to save images } } public override Image GetImage(int id) { // Some witty code to get the image from a folder in the FileSystem return null; } public override void SaveImage(System.Drawing.Image image) { // Some witty code to save the image to a folder in the FileSystem } } public class SqlImageProvider : ImageProvider { public override bool CanSaveImages { get { return true; // As we allow to save images } } public override Image GetImage(int id) { // Some witty code to get the image from a folder in the FileSystem return null; ; } public override void SaveImage(System.Drawing.Image image) { // Some witty code to save the image to a folder in the FileSystem } }

Finalmente, necesitamos crear el servicio que usa el proveedor ImageProvider. Este servicio esta ligado, o acoplado, a la definición del contrato de nuestro proveedor, pero no a las implementaciones concretas del mismo; de este modo conocerá las funciones que puede realizar pero no cómo se realizan. El servicio simplemente usa el método LoadProvider() para inicializar el proveedor que necesita (es importante tener en cuenta que el proveedor debería leerse de la configuración, y que en el ejemplo mostrado se especifica "a pelo" con propositos educativos; es necesario cambiar el código de ese método para cargar el proveedor dinamicamente de la configuración).

public class ImageService { private ImageProvider _provider; public ImageProvider Provider { get { return _provider; } } public ImageService() { LoadProvider(); } public void LoadProvider() { ProviderSettings ps = new ProviderSettings("FileSystemImageProvider", "FileSystemImageProvider_Type_Assembly"); _provider = ProvidersHelper.InstantiateProvider(ps, typeof(FileSystemImageProvider)) as ImageProvider; } public Image GetImage(int id) { return _provider.GetImage(id); } public void SaveImage(Image image) { _provider.SaveImage(image); } }

El principal incoveniente de usar el Provider Model de .NET Framework 2.0 es que hay que referenciar el assembly System.Web en proyectos que pueden ser no-web. Es necesario para acceder a la clase ProvidersHelper que instancia la colección de proveedores. Además, fuerza el uso del namespace System.Configuration para acceder a la definición del proveedor concreto a utilizar, ubicado "a la fuerza" en el fichero web.config o app.config de nuestra aplicación.

En cualquier caso, tendrás que lidiar con los tipos y nombre del assembly donde se implementan, con el objetivo de crear los ProviderSettings y pasarlos al metodo ProvidersHelper.InstantiateProvider que devuelve la instancia del proveedor concreto que deseamos utilizar. Quizás no sea recomendable usar estas referencias a los namespaces "web" en contextos de servicios o aplicaciones de escritorio, y, obviamente, existe una alternativa bastante limpia para los más puristas del contexto y la orientación a objetos :)

 

La implementación OO pura

Vale, necesitamos eliminar la referencia a System.Web y hacer que el proveedor funcione sin el modelo presentado en el .NET Framework 2.0. El primer paso es refactorizar la clase abstracta (el contrato) a un interfaz (o también dejarlo como una clase, da igual, pero hay que eliminar la herencia o implementación de la clase ProviderBase y cualquier referencia al namespace System.Configuration) y después cambiar las implementaciones concretas de los proveedores (FileSystemImageProvider y SqlImageProvider) para que usen el interfaz que acabamos de refactorizar. El diagrama de clases debería quedar tal que así:

Primero debemos crear la definición del contrato del proveedor:

public interface IImageProvider { bool CanSaveImages { get; } Image GetImage(int id); void SaveImage(Image image); }

Después, por supuesto, cambiar la definición de las implementaciones concretas de los proveedores FileSystemImageProvider y SqlImageProvider para que hagan uso del nuevo interfaz, del nuevo contrato:

public class FileSystemImageProvider : IImageProvider { // Implementation of the provider code, only signature of the class changed } public class SqlSystemImageProvider : IImageProvider { // Implementation of the provider code, only signature of the class changed }

 

 

Y finalmente, en el servicio ImageService que permanece practicamente intacto, solo hace falta modificar el código del método LoadProvider para que cree una instancia del proveedor especificado sin utilizar la clase ProvidersHelper. Algo como esto funcionaría perfectamente:

public void LoadProvider() { _provider = Activator.CreateInstance(typeof(FileSystemImageProvider)) as IImageProvider; }

 

 

¿Alguna conclusión?

Como puedes ver, el método es muy similar en ambos modelos y además es muy sencillo de implementar en la mayoría de arquitectura de software modernas. Nos proporciona facilidad de instalación, sistemas muy desacoplados y modularidad, tanto a nivel de desarrollo como de despliegue.

No hay escusa para no utilizarlo, siempre que sea posible y práctico en el contexto de vuestra arquitectura :)

Espero que sirva de ayuda a alguien.