El modelo de objetos de Visual Studio .NET El modelo de objetos
Transcripción
El modelo de objetos de Visual Studio .NET El modelo de objetos
nº18 septiembre 2005 • 6,00 € (España) Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET Framework • Windows Server System dotNetManía www.dotnetmania.com Dedicada a los profesionales de la plataforma .NET El modelo de objetos de Visual Studio .NET Tech-Ed 2005 Terminó el tiempo de espera Entrevista Alexander Vaschillo Equipo de desarrollo de SQL Server y WinFS Microsoft Corporation Laboratorio Component Art Web UI 2.1 ToDotNet Q&A ASP.NET 2.0 está aterrizando MVP Online Campus MVP Legal .NET y software libre Añadiendo nuestra aplicación al área de notificación • Ordenación de datos en Reporting Services • Atención MySQL, aquí dotNet, ¿me recibe? • Interfaces •¡Mi madre es un Singleton! dnm.editorial dotNetManía Recta final Vol. II •Número 18 • Septiembre 2005 Precio: 6€ (España) Editor Paco Marín ([email protected]) Administración Pilar Pérez ([email protected]) Asesor Técnico Marino Posadas ([email protected]) Redactores Antonio Quirós, Dino Esposito, Guillermo 'guille' Som, Jorge Serrano, José Manuel Alarcón, Luis Miguel Blanco, Miguel Katrib (Grupo Weboo) y Pedro Pozo. Colaboradores habituales Ángel Esteban, Braulio Díez, Daniel Mazzini, Eladio Rincón, Erich Bühler, Fernando Nogueras, Jorge Crespo Cano, José Miguel Torres, Miguel Egea, Octavio Hernández, Pablo Abbate, Pepe Hevia, Rodrigo Corral y Salvador Ramos. Además colaboran en este número Javier Aragonés Miranda, Carlos Quintero, Reyes García Edición y Suscripciones .netalia c/ Robledal, 135 28529 Rivas-Vaciamadrid (Madrid) Tf. (34) 91 666 74 77 Fax (34) 91 499 13 64 Publicidad Mediadev Sophie Mancini ([email protected]) Tf. 93 426 22 57 - 670 99 74 64 Fax. 93 423 11 40 Imprime Gráficas Vallehermoso www.graficasvallehermoso.com ISSN 1698-5451 Depósito Legal M-3.075-2004 << Longhorn, Indigo, Avalon... ya son nombres para la historia también. Aún no he conseguido quitarme de la cabeza a Yukon y Whidbey y ya tengo que entrenarme para decir Windows Vista o Windows Communication Foundation o Windows Presentation Foundation, o lo que es peor, las siglas WCF o WPF. Por favor, pronucie en voz alta: UVEDOBLECEEFE (y si no en inglés que es peor) y luego diga suavemente: Indigo... ¿con cuál nos quedamos...? Puede repetir con WPF y Avalon con idénticos resultados. Claro que a lo mejor es como ir con zapatillas cómodas a una fiesta de etiqueta; a todos nos gustaría más pero todos vamos con zapatos que estamos deseando quitarnos. A lo mejor el marketing es como ese tipo de normas sociales. Aunque hay empresas que han triunfado sin seguirlas, por ejemplo, Google o Yahoo, que no les dio por llamarse..., qué sé yo, GSE (Global Searching Engine), por ejemplo. ¡Y qué más da! La cuestión es que los cambios de nombres en clave por los nombres de “verdad” suponen entrar en la recta final de una etapa de grandes cambios. Porque Windows Vista Beta 1 es el principio de un gran cambio, no sólo para los usuarios de Windows, también para los profesionales de las TI y sobre todo para los desarrolladores. Ya tenemos el WinFX Runtime Components Beta 1 (para Windows Vista Beta 1) y un SDK, concretamente el Microsoft WinFX Software Development Kit for Microsoft Pre-Release Windows Operating System Code-Named Longhorn, Beta 1 (no me cebaré...), y algunas ayudas para la programación con..., pérmitame que los escri- ba por última vez, Avalon e Indigo, llamadas Visual Studio 2005 Extensions for WinFX Beta 1, para ir entrenándonos. Muchas betas 1 para la beta 2 de Visual Studio 2005, pero necesarias para que desde hoy pueda trabajar con Windows Vista y las tecnologías que están por llegar desde este otoño al verano que viene. Bienvenido al número 18 de septiembre de 2005 de dotNetManía. Le recomiendo la entrevista de Marino Posadas a Alexander Vaschillo, del equipo de desarrollo de SQL Server y WinFS en Microsoft Corporation. Ahora podemos decir, sin temor a equivocarnos, que no tenemos ni idea de cuándo saldrá WinFS (según nuestras propias fuentes). Bromas aparte, es un todo un lujo tener un mes más a otro miembro del equipo de desarrollo de SQL Server. También hemos preparado desde Ámsterdam, una esmerada crónica de Tech-Ed 2005 que espero le resulte entretenida. Si tiene pensado emprender algún tipo de proyecto en .NET bajo alguna licencia de software libre o tiene curiosidad al respecto, leáse el artículo de Javier Aragonés sobre los aspectos legales de éstas. Por supuesto, no se pierda, además no hemos publicado nada anteriormente, el artículo de Carlos Quintero sobre el modelo de objetos de Visual Studio .NET y que actualizaremos a Visual Studio .NET 2005 en el monográfico sobre éste que prepararemos para el número de noviembre. Por supuesto esto no es todo. Dentro hay más... Espero que le guste. <<dotNetManía Dedicada a los profesionales de la plataforma .NET 3 18 dnm.sumario .NET y software libre 10-13 En este artículo se aclararán diversas cuestiones jurídicas sobre derechos y licencias que se puede plantear un programador en relación con un proyecto para .NET y con el software libre. Entrevista a Alexander Vaschillo 14-16 Durante la celebración de los Academic Days 2005 en Lisboa, tuvimos ocasión de charlar con uno de los integrantes del equipo de desarrollo de SQL Server y WinFS, quien nos aclaraba algunos aspectos poco conocidos de la evolución de estas tecnologías. Tech-Ed 2005 17-20 Llegamos a Ámsterdam con el convencimiento de que la mayoría de los asistentes deseaba ver ya características aplicadas de las versiones, demos con espectáculo, trucos incipientes, y algunos de los mejores anticipos de lo que las versiones finales van a ofrecer. Y así fue… Añadiendo nuestra aplicación al área de notificación 22-25 Conseguir que nuestra aplicación apareciese en el área de notificación de Windows (como hace Messenger o una herramienta antivirus) no era tarea fácil con las herramientas de desarrollo antiguas. ¿Qué tal se porta .NET a la hora de implementar esta funcionalidad? dnm.sumario El modelo de objetos de Visual Studio .NET 26-30 Muchas de las tareas que realizamos a mano en Visual Studio .NET se pueden automatizar mediante macros y muchas otras se pueden mejorar o extender mediante complementos. En este artículo veremos el modelo de objetos que proporciona Visual Studio .NET para poder manejar el propio entorno de desarrollo desde código. Interfaces 32-34 En esta ocasión veremos más ejemplos, con idea de que nos quede claro cómo utilizar las interfaces en nuestros proyectos, aunque en esta ocasión vamos a usar las interfaces de una forma diferente a lo “habitual”, con la intención de que nos hagamos una idea de lo útiles que pueden llegar a ser estos tipos de datos. Ordenación de datos en Reporting Services 35-38 Uno de los aspectos principales en cualquier generador de informes radica en la capacidad de ordenar los datos visualizados al usuario del modo más versátil posible. Reporting Services es una herramienta que nos ayuda enormemente en nuestro trabajo como diseñadores de informes, gracias a la extensa oferta de elementos que nos ofrece para la creación de informes en general, y la aplicación de ordenamiento a los datos mostrados en particular. Atención MySQL, aquí dotNet, ¿me recibe? 39-43 MySQL es el gestor de bases de datos open source líder en la actualidad. Independientemente de la plataforma donde se esté ejecutando este, podemos conectarlo con nuestras aplicaciones .NET usando algunas de las API de comunicación entre MySQL y aplicaciones Microsoft .NET existentes. En este artículo describiremos de forma sencilla cómo realizar esta tarea con VB.NET y C#. ¡Mi madre es un Singleton! 46-48 Siguiendo con el tema del último artículo, volvemos a tratar algunos patrones de diseño básicos. En este caso veremos el singleton. Si bien puede tener dos lugares distintos de donde se llaman, siempre es la misma instancia que atiende a la petición cliente. dnm.mvp.online 49-50 Campus MVP dnm.todotnet.qa 51-53 ASP.NET 2.0 está aterrizando dnm.laboratorio.net 54-55 Component Art Web UI 2.1 dnm.biblioteca.net 57 Visual Studio Hacks (James Avery) Hackers de sitios Web (Joel Scambray y Mike Schema) dnm.desvan 58 6 noticias.noticias.noticias.noticias.noticias.noticias << dotNetManía << dnm.noticias Windows Vista El sistema operativo que sustituirá a Windows XP primero y a Windows 2003 Server después, dejará de llamarse Longhorn definitivamente para llamarse Windows Vista. El desarrollo de Longhorn, del nuevo explorador de Internet y de su modelo de programación WinFX enfilan la recta final. Primero, obteniendo sus nombres de “calle”: Windows Vista, Windows Internet Explorer 7, Windows Presentation Foundation (WPF) y Windows Communication Foundation (WCF) serán los nombres comerciales de Longhorn, Internet Explorer, Avalon e Indigo, respectivamente; segundo, con la primera beta de todos ellos: ya están disponibles la beta 1 de Windows Vista, Windows Internet Explorer y WinFX que agrupa las versiones preliminares de Avalon e Indigo (falta WinFS ); por último, se han añadido muchos recursos para los desarrolladores, tanto de la nuevas betas, como documentación, vídeos, ejemplos, herramientas, etc., en la nueva Web llamada Windows Vista Developer Center en : http://msdn.microsoft.com/windowsvista, y se ha creado una Web específica para Windows Vista en http://www.windowsvista.com. WinFX Runtime Components Beta 1 El WinFX Runtime Components Beta 1 permite a los desarrolladores experimentar con estas primeras compilaciones públicas de estas tecnologías. WCF (Indigo) es el nombre del modelo de programación para la construcción de aplicaciones de sistemas conectados. Esto extiende el .NET Framework 2.0 con API adicionales para la construcción de servicios Web seguros, fiables y transaccionales que interoperan con plataformas heterogéneas, combinando la funcionalidad de las tecnologías existentes de aplicaciones distribuidas de Microsoft (ASMX, .NET Remoting, .NET Enterprise Services, WSE y System Messaging). WPF (Avalon) es el nombre del modelo de programación del subsistema de presentación para Windows Vista. A través de él programaremos el interfaz gráfico con código administrado de .NET Framework. Esta beta 1 soporta Visual Studio 2005 beta 2 y .NET Framework 2.0. WinFX SDK para Windows Vista, Beta 1 Microsoft WinFX SDK contiene documentación, ejemplos y herramientas diseñadas para ayudarle a desarrollar aplicaciones y librerías gestionadas usando WinFX. Esta release incluye documentación acerca del uso de .NET Framework 2.0, de Windows Presentation Foundation y de Windows Communications Foundation. La documentación y los ejemplos de tecnología y aplicación -en Visual Basic, C# y C++- le servirán para comprender cómo usar los API de WinFX en el desarrollo de aplicaciones, mientras que las herramientas le serán de gran ayuda para dicho desarrollo. El WinFX SDK Beta 1 precisa de tener instalado previamente el WinFX Estándar ECMA para la especifiación del lenguaje C# 3ª edición El estándar del lenguaje de programación C# fue aprobado por primera vez por ECMA en 2002 y por ISO /IEC en 2003. A finales de junio de 2005 la asamblea general de ECMA aprobó la tercera edición de los estándares para C# y CLI, adoptando ya muchas de las características que se incluirán en Visual Studio 2005. En cuanto al lenguaje C#, el estándar ahora contiene nuevas características, tales como genéricos, tipos que pueden ser nulos y métodos anónimos, los cuales pue- den simplificar la gestión de eventos. En cuanto a CLI, ahora incluye soporte de primera clase para genéricos a nivel de runtime y de clase, además de un API paralelo que permite a los desarrolladores desarrollar más fácilmente código para la ejecución concurrente en múltiples hilos. Puede descargarse la especificación completa en formato PDF desde la URL: http://www.ecma-international.org/publications/standards/Ecma-334.htm. Runtime Beta 1 y del .NET Framework 2.0 y Visual Studio 2005 Beta2. Visual Studio Extensions para WinFX Beta 1 Visual Studio Extensions para WinFX Beta 1 proporciona a los desarrolladores soporte para la construcción de aplicaciones WinFX usando la Beta 2 de Visual Studio 2005. Éste incluye soporte de Intellisense XAML a través de extensiones de esquema para el editor, plantillas de proyecto para Windows Presentation Foundation y para el Windows Communication Foundation. El Visual Studio Extensions for WinFX Beta 1 precisa tener instalado previamente WinFX Runtime Beta 1, .NET Framework 2.0, Visual Studio 2005 Beta2 y Win FX SDK Beta 1 (mejor consulte en la Web, por si acaso...). Pueden descargarse todas las versiones desde el centro de descargas para desarrolladores de Microsoft en: http://msdn.microsoft.com/downloads. Diponibiliad Desde el 3 de agosto, Windows Vista Beta 1 está disponible para betatesters y suscriptores a MSDN y TechNet; Windows Longhorn Server Beta 1 está disponible sólo para un grupo elegido de betatesters; mientas que las primeras betas del modelo de programación y de Windows Internet Explorer 7 están disponibles públicamente. Altova presenta AltovaXML, un motor XML gratuito Altova ha presentado AltovaXML, un procesador que incluye el mismo motor de validación XSLT 1.0, XSLT 2.0, XQuery y XML que incorporan el resto de sus herramientas de desarrollo XML. Puede descargarlo de forma gratuita desde la Web de Altova en http://www.altova.com/altovaxml.html y usarlo en sus aplicaciones libre de royalties. dnm.noticias Patterns & Practices Enterprise Library de Junio 2005 Microsoft Baseline Security Analyzer 2.0 Microsoft Baseline Security Analyzer (MBSA) 2.0 es una herramienta diseñada para facilitar la detección de problemas de seguridad de los equipos de las pequeñas y medianas empresas. La nueva versión es una actualización menor de la que apareció en enero de 2005 MBSA nos ayudará a mejorar la seguridad de nuestros equipos, encontrando los errores de configuración y uso más habituales. La nueva versión ofrece un interfaz de usuario más intuitivo y más textos informativos en comparación con versiones anteriores, calificación rigurosa, búsqueda local y remota de actualizaciones de seguridad de Office XP o superior, compatibilidad con los servidos de Windows Server Update, registro y actualización del agente, automática desde Microsoft Update, sopor- Enterprise Library es una librería de Application Blocks que están diseñados para guiar a los desarrolladores en el uso de buenas prácticas de desarrollo. Aportan todo el código fuente y éste puede ser usado tal cual o modificado e incluirlo en nuestras aplicaciones. Todos los Application Blocks han sido actualizados con un particular enfoque en la consistencia, extensibilidad y la facilidad de uso e integración. Esta actualización contiene los mismos Application Blocks, pero con los parches y extensiones pedidos por la comunidad de usuarios. Puede descargarse desde: http://msdn. microsoft.com/practices/default.aspx?pull=/libra ry/en-us/dnpag2/html/entlib.asp Windows Mobile 5.0 Developer Evaluation Kit El Windows Mobile 5.0 Developer Evaluation Kit le permite comenzar a desarrollar aplicaciones para Windows Mobile 5.0 antes de la aparición oficial de Visual Studio 2005. Este kit incluye herramientas de desarrollo y recursos técnicos necesarios para desarrollar aplicaciones con Visual Studio 2005, incluyendo el propio Visual Studio 2005 Beta 2, Windows Mobile 5.0 SDK para Smartphone y para Pocket PC, Microsoft BizTalk Server 2006 Beta 1 BizTalk Server 2006 Beta 1 será compatible con el runtime de 64 bit de Windows Server 2003, .NET Framework 2.0,Windows Server 2003 R2, Visual Studio 2005 y SQL Server 2005. tibilidad para el protocolo de autenticación de correo electrónico a través del ID del remitente o el Exchange Intelligent Message Filter, mailboxes mejorados que podrán llegar a tener hasta 75 Gb, un nuevo formato para la libreta de direcciones offline, mejoras de rendimiento, etc. Puede visitar para más información los grupos de usuarios de Exchange Server (http://www.microsoft.com/technet/community/newsgroups/server/exchange.mspx) o los blogs relacionados (http://blogs.technet.com/ exchange/default.aspx). Para descargar esta CTP vaya a: http://www.microsoft.com/exchange. La beta 1 de SQL Server 2005 JDBC Driver incluye: compatibilidad con SQL Server 2000 y SQL Server 2005, compatibilidad con JDBC 3.0, rendimiento mejorado, soporte con transacción XA mejorada, soporte BLOB y CLOB, soporte con autenticación integrada, conjunto de resultados actualizable. Puede descargarlo desde: http://www.microsoft.com/sql/downloads/2005/jdbc.mspx Nuevos recursos desde Visual Studio 2005 Developer Center 101 Samples for Visual Studio 2005 http://lab.msdn.microsoft.com/vs2005/downloads/101samples/default.aspx Visual Studio 2005 Starter Kit http://lab.msdn.microsoft.com/vs2005/downloads/starterkits Vídeos para Visual Studio 2005 ediciones Express http://lab.msdn.microsoft.com/express/beginner/default.aspx dnm.noticias << dotNetManía Microsoft ha liberado la primera beta de SQL Server 2005 JDBC Driver. Esta descarga está disponible para todos los usuarios de SQL Server de forma gratuita y proporciona acceso a SQL Server 2000 y SQL Server 2005 desde cualquier aplicación Java, aplicación servidora o applet de Java. Este es un JDBC de tipo 4 que proporciona conectividad a través del estándar API JDBC disponible en J2EE. Exchange Server 2003 SP2 CTP Desde el 19 de agosto está disponible para su descarga la edición CTP del SP2 de Exchange Server 2003 que saldrá, muy probablemente antes de que este año termine. Las mejoras incluyen compresión adicional, soporte opcional de autenticación basada en certificados, mejoras del correo electrónico móvil, mejoras en la protección contra el spam, que incluye compa- ActiveSync 4.0, Microsoft Device Emulator 1.0 Community Preview, documentación y vídeos de formación. Puede solicitarlo en CD gratuitamente desde: http://msdn.microsoft.com/mobility/windowsmobile/howto/resourcekit. SQL Server 2005 JDBC Driver Beta 1 En el pasado Tech-Ed 2005 de Orlando se anunció que BizTalk Server 2006 aparecerá en la semana del 7 de noviembre junto a SQL Server 2005 y Visual Studio 2005 como parte la plataforma de la próxima generación de sistemas conectados. Sin embargo, la versión RTM (Release To Manufacturing) no verá la luz hasta el primer cuarto de 2006. Si quiere descargarse esta beta vaya a http://www.microsoft.com/biztalk/evaluation/bts2 006beta.mspx y siga las instrucciones. Exchange Server 2003 SP2 CTP es una prerelease no soportada por los servicios de soporte al cliente de Microsoft y que se distribuye con el propósito de obtener comentarios de los usuarios. te para la detección de actualizaciones de Windows 64 bit y Windows XP Embedded. Los sistemas para los que está diseñado son: Windows 2000 SP3, Office XP, Exchange 2000 o superior, SQL Server 2000 SP4 o versiones superiores. Los usuarios de los servicios de Windows Server Update deberían actualizarse a MBSA 2.0 por razones de compatibilidad. Más información en: http://www.microsoft.com/technet/security/tools/mbsa2 7 << dnm.noticias Eventos PDC 2005. Developer powered Desde el 13 al 16 de septiembre de 2005 Microsoft celebra el PDC 2005, el mayor evento mundial dedicado a las próximas tecnologías de Microsoft para desarrolladores, en Los Ángeles (CaliforniaUSA) ante miles de desarrolladores de todo el mundo. Este evento, que se celebra una vez cada dos años, reúne a los principales arquitectos de software de la compañía para exponer sus trabajos ante la comunidad de desarrolladores. Así, podremos oír de primera mano, cuáles son las nuevas características, por ejemplo, del nuevo C# 3.0 directamente del padre de C#, Anders Hejlsberg. La primera keynote correrá a cargo de Bill Gates, quien desvelará, junto con otros ejecutivos de Microsoft, las últimas innovaciones de la plataforma de Microsoft para desarrolladores. Existe una larguísima lista de ponentes, muchos de ellos ilustres, que puede consultar en la página oficial que está en: http://msdn.microsoft.com/events/pdc. Este año se focalizará en las innovaciones de desarrollo para Windows Vista, concretamente con el Windows Presentation Foundation (WPF) –antes Avalon– y Windows Communication Foundation (WCF) –antes Indigo– y la próxima versión de Office conocida en clave como Office 12. Más de 900 bloggers están contribuyendo con el sitio Web PDC Bloggers (http://pdcbloggers.net ), que proporciona a los desarrolladores una alternativa de conexión para poder comunicarse con los asistentes a la conferencia y dar su opinión a la amplia comunidad de desarrolladores. Más información en: http://www.developerpowered.com. dotNetManía estará allí Para el próximo número publicaremos un extenso resumen de dicho evento tal y como hemos hecho este mes con el TechEd Europe 2005. Nosotros también tendremos una oportunidad única de conversar con algunas de las personas que dirigen el rumbo de las nuevas tecnologías para desarrolladores para los próximos años. Os lo contaremos. Directrices de seguridad de Microsoft para desarrolladores Desde Microsoft e-learning,en español y gratuito, acaba de publicarse este curso on line sobre directrices de seguridad para desarrolladores. Esta sesión on line le proporcionará los conocimientos esenciales para la creación de aplicaciones seguras. Dividido en: fundamentos de la seguridad de aplicaciones, recomendaciones para la escritura de código seguro, defensa contra amenazas y implementación de seguridad en las aplicaciones con Microsoft .NET Framework. Los objetivos son desde comprender la necesidad de implementar la seguridad en cada fase del proceso de desarrollo, hasta las técnicas para definir modelos de amenazas, minimizar vulnerabilidades, limitar los daños causados por los ataques, etc. Más información en: https://www.microsoftelearning.com/spain/eLearning/offerDetail.asp x?offerPriceId=51363 Microsoft IT Forum 2005 Entre el 15 y el 17 de noviembre se celebrará en Barcelona el Microsoft IT Forum 2005,el evento europeo para profesionales de las TI Episodio IV de GUSE.NET << dotNetManía El pasado viernes 22 de julio se celebró en Murcia, en la CROEM (Confederación Regional de Organizaciones Empresariales), el Episodio IV del GUSE.NET (Grupo de Usuarios del Sureste de España) de cuyos orígenes ya nos habló Miguel Egea, uno de sus fundadores, el mes pasado. 8 Asistieron alrededor de 50 personas. La agenda final del evento fue: • 16:30-18:20: T-SQL Show con Itzik Ben-Gan de SolidQualityLearning. • 18:30-19:20: De DTS a SSIS con Juansa Díaz de la CAM. • 19:20-20:00: Ofertas-Demandas de trabajo. Novedades. • 20:00-20:30: Constitución fiscal y formal del grupo de usuarios como asociación. Elección de cargos y acta de constitución. En esta ocasión, el ponente estrella era Itzik Ben-Gan, socio fundador y mentor principal de Solid Quality Learning quien pudo venir gracias a la inestimable colaboración de Microsoft Ibérica. Itzik es un gurú de T-SQL, profesor y ponente habitual de conferencias como las de las reuniones de PASS (Professional Association for SQL Server), SQL Devcon o SQL Server Connections. Es autor de varios libros y artículos en revistas tan prestigiosoas como SQL Server Magazine. Además de las charlas técnicas y de los aspectos formales de la constitución del grupo de usuarios como asociación, también nos informaron sobre la inminente apertura de una Web propia, gracias a la colaboración de Microsoft Ibérica en http:/www.gusenet.com donde podremos encontrar más información a disposición de todos los miembros y del público. Las reuniones del GUSE.NET se celebran normalmente el último viernes de cada mes alternativamente en Murcia o en Alicante. Si vive o trabaja cerca le animamos a que asista y participe con ellos. Todos los eventos serán publicados en http://www.microsoft.com/ spain/eventos y es recomendable inscribirse en ellos antes de ir. Este año tenemos la suerte de ser los anfitriones (los españoles) de este evento, que se realiza ya por cuarta vez, y que posiblemente sea el evento europeo más importante para profesionales de las TI. Tres días de aprendizaje a través de entre 300 y 400 sesiones que cubrirán aspectos incluso de Windows Server R2, Windows Vista y SQL Server 2005. Los tres pilares en los que se basarán son: formación técnica, evaluación tecnológica y comunidad y networking. La keynote inicial correrá a cargo de Bog Muglia, Vicepresidente senior de la división de Windows Server. Dentro de los top speakers se encuentran: John Craddock, Mark Russinovich y Kimberly L. Tripp. La cita de este año: en Barcelona. Puede obtener más información de este evento en: http://www.mseventseurope.com/msitforum/05/pre/content/new.aspx. dnm.noticias dnm.legal Javier Aragonés Miranda .NET y software libre En este artículo se aclararán diversas cuestiones jurídicas sobre derechos y licencias que se puede plantear un programador en relación con un proyecto para .NET y con el software libre. << Cada día es más frecuente oír en una misma frase las palabras .NET y software libre, pero, ¿hasta que punto es o no una contradicción? ¿Son incompatibles? ¿Puede hacerse software libre utilizando herramientas de desarrollo de .NET? ¿Puede hacerse un proyecto de .NET utilizando herramientas de desarrollo de software libre? ¿Se puede hacer un programa inicialmente en software libre para .NET y cambiar la licencia posteriormente? ¿y al revés? ¿Quién decide qué licencia se ha de usar? A todas esas preguntas, y a otras, se dará respuesta en este artículo de manera breve y, esperemos, suficientemente clara, tras analizar, en primer lugar, qué se entiende por .NET y por software libre. ¿Qué es .NET? Puesto que los lectores de esta revista con toda seguridad lo saben mejor que yo, para contestar a esta pregunta me limitaré a citar la propia definición que hace Microsoft® al respecto1: “.NET es una plataforma de software que conecta información, sistemas, personas y dispositivos. Desarrollado con base en los estándares de Servicios Web XML, .NET permite que los sistemas y aplicaciones, ya sea nuevos o existentes, conecten sus datos y transacciones independientemente del sistema operativo, tipo de computadora o dispositivo móvil que se utilice, o del lenguaje de programación empleados para crearlo.” Javier Aragonés Miranda es abogado de Suárez de la Dehesa Abogados, despacho especializado en Propiedad Intelectual e Industrial y Nuevas Tecnologías. http://www.suarezdeladehesa.com Por tanto, se podría decir que un proyecto para .NET es todo aquel que es compatible, gracias al uso 1 http://www.microsoft.com/latam/net/introduccion/quees.asp 2 https://www.fsf.org/licensing/essays/free-sw.html de estándares, con los restantes proyectos .NET y que posibilita, facilita y potencia la interacción entre todos ellos independientemente del sistema, lenguaje, dispositivo o medio empleado, todos ellos en beneficio del usuario. ¿Qué es software libre? De acuerdo a la definición que da la Free Software Foundation, se entiende por software libre todo aquel que cumple con las cuatro libertades que ellos consideran imprescindibles2: (1) Libertad para ejecutar el programa, con cualquier propósito, (2) libertad para estudiar como funciona el programa, y adaptarlo a tus necesidades (el acceso al código fuente es un requisito para ello), (3) libertad para redistribuir copias de manera que puedas ayudar al vecino y (4) libertad para mejorar el programa, y distribuir tus mejoras al público, de tal manera que toda la comunidad se beneficia (el acceso al código fuente es un requisito para ello). En este punto conviene hacer dos aclaraciones. La primera es que software libre no es lo mismo que software gratis, o como dice el famoso aforismo, “free software is not free beer”. Si bien la palabra libre implica libertad en español, en ingles “free” puede significar tanto libre como gratis, por lo que podría llevar a interpretaciones erróneas que hacen que la gente asocie “libre” con “gratis”, cuando es perfectamente posible cobrar por el software libre, tal como Red Hat ha venido haciendo con éxito hasta ahora. << dnm.legal y/o el lenguaje en el que un programador crea un programa de ordenador y, otra muy diferente, es el resultado de esa creación, el contenido creado con la herramienta en un lenguaje determinado. ¿Son incompatibles? Una vez definido qué es .NET y qué es software libre, nada parece indicar que sean incompatibles. Es más, un proyecto para .NET podría venir a garantizar una nueva libertad al usuario: la libertad para acceder a sus datos cuándo, cómo y desde donde él quiera con la seguridad de que podrá hacerlo pues será compatible. Por tanto, desde el punto de vista de un usuario, un programa de software libre para .NET sería la mejor opción posible, pues dispondría de la mayor libertad de uso que se puede conseguir. Ahora bien, para determinar si desde el punto de vista de un programador o de una empresa desarrolladora de software esa opción resulta o no igual de beneficiosa son muchas las cuestiones que deberían analizarse, todas ellas perfectamente válidas y posibles, que dependerán de la estrategia empresarial que se elija, en la que aquí no vamos a entrar. Cuando un programador o una empresa tiene en mente el proyecto que quiere abordar, o el que le han encargado que desarrolle, surgen diversas opciones y cuestiones que han de ser concretadas, como cuál es la licencia que se quiere emplear (propietaria, libre, de código abierto), quién será el titular, etc., por ello se hace necesario explicar algunos conceptos antes de entrar a hablar de las licencias y cesiones de derechos. Herramientas y creaciones Lo primero que hay que dejar claro es que una cosa es la herramienta Cada programador elije la herramienta de desarrollo que quiere emplear para crear un programa de ordenador. Dicha herramienta de desarrollo no es otra cosa que un programa de ordenador creado por otro programador X o por una empresa y, como tal, habrá que disponer de una licencia de uso para emplearlo, pero ello no significa que el titular de esa herramienta de desarrollo, el programador X, tenga algún derecho sobre lo que un programador cree utilizando ese programa. Dicho de manera sencilla: una cosa es el programa Word que estoy empleando para escribir este artículo, que es titularidad de Microsoft®, y otra diferente es el artículo en sí, del cual yo soy el único titular, y sobre el cual Microsoft® no ostenta ningún derecho pese a que yo lo he creado usando su programa. Lo mismo es predicable de un programa desarrollado para .NET por un programador. Independientemente de la herramienta (o programa) de desarrollo que emplee para su creación (Visual Studio .NET, .NET Framework, ASP.NET, Mono, etc.) el programador será, en principio, el único titular de su creación, sin que el creador de la herramienta empleada tenga algún derecho sobre ello. La importancia de emplear uno u otro es la posibilidad de acceder a la creación. Yo he creado este artículo con Microsoft® Office Word 2003, con lo cual sólo lo puedo abrir para editarlo con un programa compatible, igual que sucede con el código fuente de un programa, que sólo puede editarse con un programa compatible con aquel en el que se creó, de ahí la importancia de elegir un programa o lenguaje determinado sobre otros. El resultado del trabajo de un programador es, en principio (ya lo veremos) de su exclusiva titularidad y puede hacer con él lo que le apetezca. Puede regalarlo, borrarlo, venderlo, grabarlo en un CD y guardarlo en un cajón, etc. En fin, un programador es libre de hacer, en principio, lo que quiera con el programa que ha creado pues para eso es su creación y, por tanto, puede licenciarlo como quiera o no licenciarlo en absoluto. La titularidad Acabamos de ver que un programador es libre, en principio, de hacer lo que quiera con el programa que ha creado. Y se dice “en principio” pues en la legislación de propiedad intelectual existen unas presunciones según las cuáles si un programador trabaja para una empresa, será ésta la titular de los derechos sobre la creación del programador e, incluso, puede llegar a ser considerada la propia empresa como autora del mismo. El artículo 97 de la Ley de Propiedad Intelectual establece cuatro clases de titularidad respecto de un programa de ordenador en función del proceso de creación: 1. Creación individual.- Cuando un programador crea solo, por su cuenta, él es el único titular del programa que crea, y si crea para alguien, debería existir un contrato entre ambos que regule la cesión de los derechos, si es que cede alguno. Un <<dotNetManía La segunda es que software libre no es sinónimo de software de código abierto o software abierto (open source). Pese a que se usan indistintamente en muchas ocasiones, no son sinónimos. Si bien todo el software libre es software abierto, pues el acceso al código fuente es un requisito de dos de las cuatro libertades, no todo el software abierto cumple las cuatro libertades necesarias para ser considerado libre, ya que puede que un programa de código abierto sólo me permita adaptarlo pero no distribuirlo. 11 << dnm.legal ejemplo de este tipo serían la mayoría de pequeños programitas freeware y shareware que pueden encontrarse por la red. 2. Creación colectiva.- Cuando un programa se crea por varios programadores bajo la iniciativa y coordinación de una empresa o de una persona, a no ser que se pacte lo contrario, esta empresa o persona se considerará autora del programa y, en consecuencia, será la titular de todos los derechos sobre el mismo. El ejemplo sería cualquier corporación (Microsoft®, Adobe®, etc., etc.) 3. Creación colaborativa.- Cuando un programa se crea por varios programadores que colaboran entre sí, todos ellos será coautores del mismo y a todos ellos corresponderá su titularidad en las proporciones que establezcan. Como ejemplo estarían la mayoría de proyectos de software libre, o un programita creado entre varios amigos. 4. Creación asalariada.- Cuando un programador crea un programa dentro de las funciones que desarrolla como asalariado de una empresa, él seguirá siendo el autor pero los derechos de explotación pertenecerán en exclusiva a la empresa. Ejemplos serían la mayoría de relaciones laborales de los programadores. <<dotNetManía [ 12 Software libre no es lo mismo que software gratis ] Una vez que se determina a quién corresponde la titularidad de un programa de ordenador, será a esa persona o empresa a quien corresponda decidir la licencia que se aplicará al programa, pues la condición de titular es la que permite decidirlo. (Por brevedad, en este artículo al referirme a programador me refiero al titular, a no ser que se entienda claramente lo contrario.) Las licencias Una licencia es el conjunto de reglas que el programador establece para que el resto de personas en general pueda interactuar con su programa. El programador establece en la licencia lo que permite que el usuario de su programa haga con el mismo (como, por ejemplo, instalarlo en todos los ordenadores de su casa) y también lo que se le prohíbe hacer expresamente (como hacer una copia y colgarla en su blog a disposición de todo el mundo, por ejemplo). Por ello, lo primero que ha de decidir es qué es lo que quiere permitir hacer a los usuarios y establecer una licencia, que puede redactarse expresamente para ese programa, o puede usarse una de las existentes si se adapta a lo que se quiere. A la vista de lo expuesto, se puede afirmar que sí es posible realizar proyectos de software libre para .NET, pues el programador puede utilizar para su creación una licencia de software libre (que otorgue al usuario las cuatro libertades mencionadas al inicio) de igual forma que puede hacer que el programa que cree sea de código abierto o propietario. Entra perfectamente en las facultades del programador decidir lo que los usuarios hagan con su programa, independientemente de la herramienta de desarrollo que emplee en su trabajo. Un programador que utilice Mono™ (la herramienta de software libre para desarrollo de proyectos .NET multiplataforma) puede licenciar el programa creado con la licencia que quiera, incluso propietaria, de la misma manera que un programador que utilice Visual Studio® .NET puede convertir el programa creado en software libre aplicando la licencia adecuada para ello. Cambio de licencia Una cuestión que puede plantearse un programador es si puede cambiar la licencia de un programa por otra diferente una vez que ya se haya distribuido. La respuesta, como la mayoría que puede dar un abogado, será “depende”. Y la posibilidad de cambio depende de la licencia o del contrato que ya haya [ Un proyecto bajo .NET puede perfectamente ser software libre ] otorgado respecto del programa. Para que ello no sirva de excusa para evitar la respuesta, expondré unos criterios que pueden emplearse de manera general, aunque luego haya que examinarse caso por caso. El criterio general que ha de emplearse es el de conservación y mantenimiento de los derechos cedidos. Si con una licencia se ceden a los usuarios unos derechos, que han estado disfrutando pacíficamente, éstos mismos usuarios no pueden verse perjudicados por la decisión del programador de modificar los términos de la licencia y, por tanto, esos cambios operados no les afectarán durante el periodo de vigencia de la licencia que les ampara. Una primera cuestión que hay que examinar es si la licencia es en exclusiva o no. Aunque lo normal es que las licencias de los programas son no exclusivas, es decir, se puede ceder el programa tantas veces como usuarios haya, es posible que un programa desarrollado a medida para una empresa sí se ceda en exclusiva, lo que significa que nadie (incluido el propio programador en la mayoría de las ocasiones) puede usar ese programa sin permiso de la empresa. Ello conllevaría que el programa no pueda cambiarse de licencia por el programador pues, aparte de que probablemente se lo prohíba el contrato, si cambia de una licencia exclusiva a una no exclusiva estaría perjudicando a la empresa a la que cedió en exclusiva, pues lo normal es que las licencias exclusivas cuesten más dinero y sirvan para que la competencia no use el mismo programa. Lo que sí puede hacerse es cambiar una licencia no exclusiva a una exclusiva, pero con ello no puede perjudicarse a aquellos usuarios que han venido usando el programa porque la licencia se lo permitía. En estos casos el programa caerá en desuso, pues a medida << dnm.legal [ ] El programador es quien decide qué licencia quiere dar a su programa Cuestión distinta es si con el cambio de licencia se limitan los derechos del usuario. Como ya se ha mencionado, si se limitan los derechos ya concedidos, ese cambio no puede perjudicar a los usuarios amparados en la licencia más amplia, pues mientras dure el término de la misma se encuentran perfectamente amparados. Con las actualizaciones y sucesivas versiones, que sí se regirán por la nueva licencia más restrictiva, el problema se minimiza, pues si un usuario quiere beneficiarse de las mismas deberá aceptar la nueva licencia, y ya sólo será cuestión de tiempo que los usuarios que dispongan de la vieja licencia vayan desapareciendo. Por este motivo, lo recomendable es aprovechar el lanzamiento de una nueva versión para realizar el cambio de licencia, incentivando así su adopción por parte de los usuarios. 3 4 Pese a la sencillez del proceso expuesto, la transición de licencia puede ser más complicada si se hace de software libre a propietario, pues si es software libre, lo normal es que la licencia sea de duración indefinida, con lo que los usuarios podrán redistribuir, adaptar y actualizar el programa. En estos casos, el futuro del programa libre depende (1) de que se cree una comunidad de desarrollo, pues si no se crea, lo normal es que caiga en desuso, (2) del precio y (3) de las novedades que se introduzcan en el nuevo código, pues si estos últimos son atractivos los usuarios los preferirán. Existen numerosos ejemplos de cambios en las licencias. Un ejemplo de paso de software libre a propietario sería el programa denominado Yanoff (programa de lectura de noticias para Palm OS) que cambió de ser software libre bajo GPL (licencia más usada de software libre) a ser código cerrado. En el sitio Web del programa se reconoce que los usuarios anteriores podrán seguir desarrollando el mismo en la versión de 2003, pero no en las posteriores. En el sentido contrario, de software propietario a software libre, uno de los ejemplos más notables se ha dado con OpenOffice.org, la suite de ofimática que pasó de ser propietaria a tener doble licencia, una comercial y una libre (LGPL), y que actualmente se está pensando en pasarlo todo a GPL. Otro ejemplo anunciado recientemente se ha dado respecto del código fuente del juego Quake III, que la empresa desarrolladora del mismo piensa distribuir bajo la licencia GPL. Proyectos modelos Todo lo dicho con anterioridad solamente es aplicable a los programas creados íntegramente por el programador, ya que si el programador introduce código no original en el programa que desarrolla, ha de respetar la licencia bajo la cual se ha distribuido dicho código. Esta cuestión tiene especial relevancia en el desarrollo bajo .NET, pues en las herramientas de desarrollo se suelen incluir http://www.asp.net/samplessourcelicense/Default.aspx http://www.dotnetnuke.com/Default.aspx?tabid=776 [ ] Los cambios de la licencia no pueden perjudicar los derechos de los usuarios actuales proyectos, módulos y rutinas modelo que pueden ser empleadas por el programador. Dicho código modelo solamente podrá ser empleado si se respeta la licencia del mismo, que puede, o no, permitir su distribución como software de código abierto. Por ejemplo, en la licencia de Microsoft® ASP.NET Source Projects3 se establece que se puede utilizar el software modelo con finalidad comercial pero expresamente establece que no puedes combinarlo o distribuirlo con software cuya licencia requiera que se suministre el código fuente. Sin embargo, también hay ejemplos que sí permiten la modificación y distribución del código fuente, como DotNetNuke, desarrollado con ASP.NET, cuya licencia4, denominada X11 o MIT, es una licencia de software libre. Por tanto, antes de emplear código ajeno en un programa propio conviene examinar la licencia del mismo para determinar lo que se puede y no se puede hacer, pues de otra manera se corre el riesgo de infringir los derechos de sus titulares. Conclusión De todo lo expuesto se deduce que un proyecto desarrollado para .NET puede licenciarse de la manera que mejor se adapte a la estrategia comercial del titular de los derechos del mismo, pues puede hacerlo como software de código abierto, propietario o libre, sin que en ello influya la herramienta empleada en su desarrollo. Y si la estrategia comercial cambia, con ella también puede modificarse la licencia, respetando el principio general de no perjudicar los derechos de los usuarios actuales. <<dotNetManía que dejen de usarlo los usuarios que estaban amparados por la licencia, ningún otro podrá usarlo salvo el que tenga la licencia exclusiva. Un segundo grupo de cuestiones que ha de analizarse es si con el cambio de licencia se limitan o se amplían los derechos ya concedidos. En el supuesto de que se amplíen los derechos o posibilidades de uso que proporciona una licencia no exclusiva, es perfectamente posible ese cambio, pues el usuario no se ve perjudicado por ello, más bien todo lo contrario, pues ahora tendrá más facultades de las que podrá, o no, aprovecharse. Por ejemplo, si sólo se permite la instalación en un ordenador, y se cambia la licencia para que puede instalarse en tres, se está beneficiando enormemente al usuario y no se le perjudica en nada. 13 dnm.directo.entrevistas Marino Posadas Entrevista a Alexander Vaschillo Durante la celebración de los Academic Days 2005 en Lisboa, tuvimos ocasión de charlar con uno de los integrantes del equipo de desarrollo de SQL Server y WinFS, quien nos aclaraba algunos aspectos poco conocidos de la evolución de estas tecnologías. << ¿Tu trabajo es en investigación y desarrollo o solamente Marino Posadas es asesor técnico y redactor de dotNetManía, MVP de C# y formador de Alhambra-Eidos en desarrollo? En la actualidad estoy en desarrollo, exclusivamente. Trabajo en grupos de desarrollo, casi siempre vinculados a la gestión de bases de datos y tecnologías relacionadas con ellas, como los Object Spaces anteriormente, o la tecnología vinculada a WinFS, el futuro subsistema de almacenamiento de Longhorn. Hace unos meses tuvimos ocasión de hablar también con Andrew Conrad, del equipo de desarrollo de Object Spaces. La reacción de los lectores que seguían el tema, fue de sorpresa, al saber que esa tecnología no estaría visible, sino embebida en el subsistema, y no utilizable directamente, como un API… Object Spaces ha sido una tecnología en evolución y realmente, Microsoft no ha publicado en ningún momento que tal tecnología fuese a estar disponible “desde fuera”, como tú comentas. Tienes razón en el sentido de que se pensó que podría accederse desde fuera, pero desde un inicio, la tecnología estaba pensada para usarse de forma interna. WinFS, de hecho, utiliza esta tecnología y también un lenguaje especial de consultas, como mostraba yo antes en uno de los ejemplos de mi conferencia. Otra pregunta que está provocando ríos de tinta, especialmente en la prensa especializada de los Estados Unidos, es si, realmente, WinFS va a estar dentro de Longhorn de alguna forma, –aunque no en su ámbito total de desarrollo– o es que no va a estar en absoluto, aunque pueda aparecer como una beta instalable. ¿Qué puedes decirnos al respecto? Bueno, –y esto es una de las cosas de las que tengo miedo a pronunciarme– creo que lo cierto es que no va salir como parte de Longhorn, ni en parte, ni en su totalidad. Pienso que aparecerá un cierto tiempo después, aunque no podría decir cuánto tiempo. La buena noticia es que será capaz de funcionar en otros sistemas operativos, y no sólo en Longhorn. ¿Quizá una parte de esta funcionalidad estará presente por defecto en Longhorn? Aunque sea una pequeña parte… No. No lo creo. Pongamos la pregunta de otra forma. ¿Habrá en Longhorn algún tipo de tecnología, –aunque no sea WinFS– que mejore la experiencia de búsqueda de información en el sistema, se llame como se llame? Alexander Vaschillo << dnm.directo.entrevistas Alexander Vaschillo y Marino Posadas ¿Y qué hay de las posibilidades de su utilización como mecanismo de integración, tanto en aplicaciones como en flujos de trabajo entre plataformas o aplicaciones distintas, al estilo de lo que hace BizTalk Server ahora? Creo que lo cierto es que no va salir (WinFS) como parte de Longhorn, ni en parte, ni en su totalidad. La buena noticia es que será capaz de funcionar en otros sistemas operativos, y no sólo en Longhorn XML es un concepto para permitir la integración y la transmisión de información independiente de su formato original o su destino final. Por tanto, no sólo es cierto lo que propones, sino que se va extender a otras herramientas como SharePoint desde el punto de vista de la integración. Además, esto resolverá problemas que los usuarios de las características de XML de la versión 2000 de SQL Server habían mencionado a la hora de la utilización de los esquemas de los datos que se manejaban. Por supuesto, el otro punto fuerte de esta nueva versión es la integración con el CLR. ¿Crees que esa característica será suficiente para una migración? bién, en el caso de consultas realmente complejas que podrían ser abordadas de otra forma novedosa en esta forma. Has comentado en tu charla, que un procedimiento almacenado (desde esta óptica), se puede convertir en un servicio Web. Incluso que podremos convertir procedimientos almacenados existentes en servicios Web. Esto nos lleva a una pregunta natural asociada con esto. ¿Qué va a suceder con las Extensiones de los Servicios Web (WSE)? En efecto, todo eso va a ser posible en la próxima versión. Pero no puedo contestarte a esta pregunta en este momento. La tecnología de la que yo era responsable, tenía que ver con SQL/XML, <<dotNetManía Con toda seguridad existirán mejoras a ese respecto, pero tendrán más que ver con tecnologías que, si bien no están vinculadas a WinFS, permitirán un uso más rico de las posibilidades de búsqueda de información en el sistema. Bien, sigamos hablando de tecnologías vinculadas con SQL Server y el almacenamiento. Una de las novedades más importantes en SQL Server 2005 es el tipo de datos XML ¿Podrá ser utilizable incluso en arquitecturas de almacenamiento Web, para guardar páginas de contenido (XML) y páginas de presentación (XSL) de forma que se pueda tener –literalmente– guardado un sitio Web en campos de una base de datos? Sin duda. Es más, nosotros pensamos que con el tiempo será el mejor sitio posible para el almacenamiento de información, pero sobre todo, por que podremos hacer búsquedas dentro del propio contenido del campo. Digamos, por ejemplo, que podremos pedir a SQL Server que nos seleccione un conjunto elementos de cierto nombre o que posean algún atributo concreto, y estén incluidos dentro de la estructura del fichero XML almacenado en un campo. O extender esa búsqueda a todos los campos XML de una tabla en busca de elementos relacionados por nombre, atributo o valor. Ese creo que será uno de los usos más importantes de esta tecnología. ¿O que será lo suficientemente comprendida como para motivar la migración a esta versión? Para situaciones diferentes, respuestas diferentes. Somos conscientes que –a la fecha de hoy– hay gente a la que esa característica le trae sin cuidado. Existen otros, sin embargo, que han estado esperando la oportunidad de almacenar objetos dentro de la base de datos, y esa oportunidad se la brinda ahora esta nueva versión. Dependerá de cada aplicación concreta si la tecnología se aplica inmediatamente o no. ¿Crees que el perfil típico del desarrollador típico de SQL Server se adecua a la incorporación inmediata de estas novedades, o requerirá una fuerte curva de aprendizaje? Yo no creo que sea un problema. La aceptación de .NET es y seguirá siendo creciente, y su conocimiento, también. Cuando el desarrollador vea que hay formas de hacer cosas con menos esfuerzo y más fiabilidad, irá adoptando la tecnología, como se ha hecho siempre. O tam- 15 << dnm.directo.entrevistas <<dotNetManía La aceptación de .NET es y seguirá siendo creciente, y su conocimiento, también. Cuando el desarrollador vea que hay formas de hacer cosas con menos esfuerzo y más fiabilidad, irá adoptando la tecnología, como se ha hecho siempre 16 y la forma en que esto se ve desde el punto de vista externo. Veremos qué sucede en los próximos meses… Otro punto de confusión que me gustaría aclarar aquí es la posibilidad de almacenar ficheros en un campo de la base de datos. Cuando oí esto, al principio pensaba que se almacenaría un “puntero” por así decirlo, a la posición física de ese fichero, junto a información relacionada con él. Pero tú has comentado que se trata de un almacenamiento real del fichero dentro de un campo de una tabla de base de datos… Su uso depende del contexto y del propósito de uso que el fichero tenga. Pongamos que hablamos del formato JPG. Una de las necesidades que se plantean es hacerlo de forma que se puedan incluir estos campos en consultas especiales capaces de devolver información adecuada acerca de esos datos. El otro punto a tener en cuenta, es que si utilizas un tipo de almacenamiento común para ficheros que –originalmente– son bien distintos, en la salida se debe de tener una idea clara de cuál es ese formato, para poder utilizarlo. No sé si esta va a ser la utilización óptima en la actualidad. Quizá lo sea en el futuro y WinFS almacenará realmente cualquier tipo de información para servirla en la forma adecuada a quien la solicite, pero en la actualidad, esa no es la idea, o al menos, no en su sentido global. La utilización ideal de esta tecnología será cuando existan más tipos de datos adecuados a los distintos tipos de almacenamiento, pero quizá eso requiera de más potencia de ordenador y sólo tenga sentido dentro de unos años, cuando esa potencia esté disponible ampliamente. A propósito de potencia de almacenamiento, James Gray decía que la potencia vinculada al hardware tendrá un gran impacto en cómo usamos el software, puesto que un disco duro de dentro de 10 años, será –en sí mismo– un ordenador como los actuales, con su CPU, su memoria, etc. Entonces, el problema principal (como ya lo es hoy) será el del acceso. ¿Podríamos ver en un futuro a WinFS presente en cada dispositivo de almacenamiento vinculado a un sistema que soporte .NET Framework? Es una idea interesante. Y, efectivamente, así son las cosas hoy día. Probablemente, la línea de investigación más importante, una vez solventados los problemas de almacenamiento sea la del acceso a esa información almacenada. Tenemos que ver WinFS como una capa por encima de cualquier tipo de almacenamiento. Un día estará presente incluso en los teléfonos móviles. Siempre que hablo de bases de datos tengo que referirme a las bases de datos orientadas a objetos. ¿Las ves factibles, entonces, con la tecnología actual? WinFS es una capa por encima de la tecnología de acceso a bases de datos. Ahora conocemos bien los entresijos del funcionamiento óptimo de una base de datos relacional. El problema es conseguir que esos objetos se almacenen en un motor relacional bien dimensionado y optimizado, de la misma forma que ahora. De momento, esta tecnología nos puede ayudar a solventar el problema que planteaba Jim Gray y que él mismo está contribuyendo a resolver. Que el propio mecanismo de acceso a la información se vuelva más lógico, más apropiado para la forma en la que los seres humanos necesitamos acceder a la información. De todas formas, siempre va a existir algún tipo de búsqueda de la información, pero la forma en que organicemos su almacenamiento y construyamos los mecanismos para su acceso, serán vitales para el tiempo de respuesta adecuado. Para concluir, una comparación respecto a la importancia tecnológica a largo plazo de los 3 subsistemas de Longhorn: Avalon es la cosmética: muy bonito, muy espectacular, pero su aportación se detiene ahí. Indigo es más importante, creo, porque son comunicaciones. Pero WinFS es crítico, porque se trata de cómo se comporta nuestra información, cómo se almacena, y cómo se recupera. ¿Estoy en lo cierto? Para mí, totalmente cierto. Incluso lo que los otros dos subsistemas manejan (y manejarán) seguirá siendo información que se almacena, se lee, se transforma, se transporta y se vuelve a almacenar. Esa secuencia es, efectivamente, crítica en el comportamiento de cualquier sistema operativo, y lo va a ser todavía más en Longhorn, y los sistemas venideros. Muchas gracias por tu visión de futuro y hasta la próxima. Gracias a vosotros. << dnm.directo.eventos Marino Posadas Tech•Ed Europe 2005 << El lector veterano de dotNetManía quizá recuerde que Andrew Lees durante la “keynote” inicial (la maza asoma como amenaza) Nos recibió Andrew Lees, con una keynote (o conferencia principal), en la que presentaba los dos productos como fruto de dos principios: la madurez en la plataforma, debido a tratarse de un tercera versión, y el “feedback” de los usuarios, inclusive durante el período de desarrollo. Presentó un nuevo SQL Server, mucho más maduro en todos sus aspectos, con una plétora de nuevas y reforzadas opciones, nuevos servicios, nuevas formas de construir la capa de datos en las aplicaciones y un sistema de réplicas y tolerancia a fallos, que llegaba al momento culminante cuando, –maza en mano– vuelve a aparecer en plena demostración de peti- En la entrevista con Brian Keller, Product Mannager de Visual Studio ciones a servidores y destruye –literalmente– uno de los equipos, que salta por los aires, mientras el otro servidor se hace cargo de las peticiones que le llegaban al equipo destruido y permite seguir funcionando como si nada: “Esto es tolerancia a fallos”, añadía, entre los aplausos de toda la audiencia, encandilada por una demo tan contundente y clara como efectista. En otra de las demos, Brian Keller, Product Manager de Visual Studio, (con quien tuvimos ocasión de hablar posteriormente), nos mostraba lo tremendamente sencillo que resulta crear aplicaciones Web o Windows con el nuevo Visual Studio 2005, incluyendo, casi de fábrica, las capacidades de mantenimiento completo de una tabla de una base de datos cualquiera, sin tener que escribir una sola línea de código fuente. Una característica de productividad que agradecerá todo aquel que tenga que abordar tareas rutinarias de mantenimiento. Y esto, funcionaba exactamente igual para Windows que para las aplicaciones Web. Posteriormente, mediado el evento, tuvimos ocasión de asistir a una segunda keynote, realizada por David Vaskevitch, quien nos aportada la sabiduría acumulada al frente de la construcción de aplicaciones en Microsoft, para analizar la evolución del software, desde hace 10 años hasta ahora, y justificada en esa evolución, extrapolar las tendencias y las promesas de los fabricantes, para acabar dibujando un perfil muy evolucionado en el que el software es cada vez más inteligente, más próximo al usuario final, y Microsoft, y las herramientas que allí se presentaban, sus valedores tecnológicos, gracias a un proceso de innovación continua, fruto de las elevadas inversiones en investigación, llevadas a cabo por Microsoft << dotNetManía el año pasado, a la vuelta del evento de Ámsterdam, titulábamos nuestra crónica como de un tiempo de espera. Bien, la espera ha concluido, y –si bien las anunciadas versiones de VS 2005 y SQL Server 2005 no verán la luz hasta noviembre de este año–, las betas con las que estamos trabajando y el material expuesto en esta edición del Tech-Ed, muestran un grado de madurez suficiente como para poder evaluar estas betas con conocimiento de causa. Llegamos a Ámsterdam con el convencimiento de que la mayoría de los asistentes deseaba ver ya características aplicadas de las versiones, demos con espectáculo, trucos incipientes, y algunos de los mejores anticipos de lo que las versiones finales van a ofrecer. Y así fue. 17 << dnm.directo.eventos David Vaskevitch, durante su exposición en la segunda keynote Research, y cuya tendencia parece seguir en crecimiento. Más profunda, y también más filosófica que la anterior, la charla de Vaskevitch, venía a recordarnos que la evolución tecnológica es ya un fenómeno imparable y la empresa que quiera mantenerse viva, debe participar de esa corriente de renovación, adoptando las novedades en inicio, y ofreciendo a sus clientes las últimas posibilidades tecnológicas con conocimiento del medio. La organización de contenidos, las ponencias y… los ponentes << dotNetManía Al igual que el año pasado, las sesiones se dividían en varios bloques troncales, o tracks, tales como Seguridad, Herramientas de Desarrollo, Gestión Operativa, Inteligencia de negocio, etc, a los que precedían un día de PreConferences, con una oferta de seminarios de gran calidad, y charlas con gurús, como Steve Railey (en seguridad), Jeff Prosise (a quien también entrevistamos) o Kimberley Tripp (SQL Server), quienes también nos regalaron algunas de las mejores ponencias de este TechEd. 18 Durante la entrevista con Jeff Prosise… un sabio Birds-of-a-feather: reuniones de café con equipos de desarrollo Los más de 6.500 asistentes nos fuimos repartiendo por las sesiones en una búsqueda entre la calidad de las ponencias en sí, y el interés personal en los contenidos, que casi siempre concluía con éxito. Citar aquí todo lo bueno que se vivió en las salas es difícil, pero la personalidad de algunos ponentes era innegable: Juval Löwy, conciso y elegante en su visión de las peculiaridades de la nueva versión de Visual Studio, arrancó varias veces los aplausos de la audiencia, mostrándonos la nueva herramienta, y con una excelente visión popular, enfatizando siempre aquellas partes más productivas. Incluso superior fue el efecto en el público causado por el showman Steve Railey, en sus charlas sobre seguridad. Metido entre el público, interrogando en directo, y haciendo que las respuestas in situ fueran la ocasión para continuar de forma natural sus argumentos, abarrotó las sesiones en las que participaba, dejando en la audiencia siempre un mensaje entusiasta. También fue muy celebrada la presentación de Jeff Prosise, en el auditórium, con su charla sobre seguridad en el código fuente aplicada a la construcción de sitios Web con ASP.NET. En el inter- viú que nos concedió posteriormente y que publicaremos en su momento, nos confesaba su abandono de las labores de autor de libros (su última obra fue “Programming.NET Framework”), para concentrarse exclusivamente en la escritura de artículos (inaugura una nueva sección en MSDN Magazine a partir de este mes de septiembre), las conferencias por todo el mundo y la formación y consultoría. Con Ari Bixhorn, Lead Product Manager de la estrategia de servicios Web Tampoco pudimos asistir a todas las charlas que nos hubiera gustado por razones operativas y de tiempo, pero me gustaría recordar con algunos adjetivos a los que destacaron por méritos propios: el entusiasmo y calidad de Ari Bixhorn (Lead Product Manager de la estrategia de servicios Web), cuando presentaba Indigo, la cohesión y secuencia lógica de la exposición de Kimberley Tripp en sus varias charlas sobre aspectos diversos de SQL Server 2005, la visión Juval Löwy en un momento de su ponencia << dnm.directo.eventos simplificadora de Ingo Rammer, centrado en el rendimiento, escalabilidad y disponibilidad de los sistemas construidos con .NET Framework, junto a otro de nuestros entrevistados, Arvindra Sehmi, un profundo conocedor de las arquitecturas de .NET y de SOA en particular. Mark Russinowitch, al igual que ya hiciera el año pasado, volvió a recordarnos cuán vulnerables son nuestros sistemas a ataques de todo tipo utilizando –a veces– los más contundentes argumentos en forma de demos, que ponían en evidencia muchas prácticas habituales en la construcción de aplicaciones. Similares –por su contundencia lógica– resultaron muchas de las recomendaciones del veterano Gert Drappers, ya fuera al referirse a la afinación de servidores para obtención de rendimiento, o al analizar –y después comparar– las capacidades ofrecidas por la integración del CLR en el motor de SQL Server, respecto a las posibilidades añadidas al lenguaje T-SQL. Otros viejos conocidos que estuvieron por allí y captaron la atención mayoritaria, fueron Rafal Luckawiecki, quien introdujo con su carisma habitual algunas novedades de la que será la versión 4 del marco de tra- Rafal Luckawiecki Con Sean O'Driscoll, Director del Programa MVP en Redmond términos de calidad de los seleccionados, de propuestas de colaboración, y de reconocimiento empresarial del valor añadido que suponen sus miembros. Los asistentes: el otro Tech-Ed Microsoft se ha empeñado en una campaña para unir los intereses comunes de los desarrolladores a través de herramientas comunitarias. Podemos verlo nada más que abrimos la beta 2 de Visual Studio (con un nuevo elemento de menú que nos pone en contacto con recursos de comunidades), y pudimos comprobarlo sobre el terreno, a través de las variadas iniciativas que –en ese sentido– poblaban todos los rincones del RAI. Por un lado, unas reuniones informales de café (en un café), con integrantes de distintos equipos de desarrollo de los productos (Birds-ofa-feather), o las asesorías gratuitas ofrecidas por la iniciativa Ask-the-Experts, en las que expertos de hasta 12 tipos de tecnologías distintas, respondían personalmente a las preguntas de usuarios interesados. Por otro, reuniones de comunidades, como la ofrecida en el MVP Community Lounge, para los MVP asistentes, a la que compareció, como el año anterior, el Director Mundial del Programa MVP, Sean O'Driscoll, quien estuvo haciendo balance, de la evolución del programa MVP en Una vista general de los Hands-on-Labs También estaban disponibles más de 250 equipos para albergar los populares HOL (Hands-on-Labs), prácticas de laboratorio dirigidas y/o asistidas, donde podemos aprovechar la oportunidad para introducirnos en una tecnología de forma guiada. Las sesiones Chalk & Talk, aprovechaban los tiempos de descanso, para dar respuesta a preguntas de los asistentes en directo, que también podían participar –solicitando respuestas con anterioridad–, en las Panel Discussions, que, moderadas por un experto en el tema de discusión, comentaban las respuestas a las preguntas propuestas, en el marco general de la sesión e incluso admitían puntualizaciones en directo para soporte y apoyo de las soluciones propuestas. Parece que continúa –en general– la tendencia a facilitar la participación real de los asistentes en los contenidos y realización de ciertos aspectos de estos eventos. << dotNetManía Mark Russinowitch, en su conferencia sobre virus bajo para aplicaciones Microsoft, la MSF 4.0, el extrovertido Brian Goldfarb (a quien el lector recordará que entrevistamos a su paso por Madrid), quien presentó muchas de las novedades de ASP.NET 2.0, la polivalente Michelle Lerroux Bustamante, interesada en servicios Web y en migraciones desde Java, o Tony Goodhew, que anticipaba algunas de las que se convertirán –en breve– en buenas prácticas para la construcción de interfaces de usuario que resulten fáciles de migrar a Avalon, cuando la plataforma esté disponible en su versión definitiva. Y por cierto, no se habló demasiado de Longhorn (quiero decir, del que ahora sabemos que se llamará Windows Vista) en términos de producto, sino que se realizaron varias presentaciones vinculadas a aspectos muy puntuales del sistema, como nuevas características de seguridad, o las dos API que se han popularizado a través de versiones CTP (Avalon e Indigo) y que sabemos que podrán instalarse en los equipos actuales. Esto, sin duda, resultará un acicate para la migración al nuevo sistema, una vez que vayamos observando sus posibilidades. 19 << dnm.directo.eventos La representación española y la Universidad Olvido Nicolás (TechNet), Carlos Oramas (Grupo de Soporte), y Alberto Sánchez (relaciones con Universidades), de Microsoft Ibérica, llevaron el peso de la representación española, que, en el apartado universitario era bastante numerosa, con asistentes de muchas facultades de informática españolas, (ver foto de grupo adjunta), que encontraron tiempo, para hacer un poco de todo, y continuaron el proceso de divulgación de la tecnología .NET que comenzara ya hace varios años, y se ha traducido en varias iniciativas en forma de asignaturas en la carrera de Informática, seminarios y masters impartidos en facultades de toda nuestra geografía. Los representantes de prensa, impecablemente atendidos por Mónica García de la agencia Ketchum/SEIS, también tuvimos oportunidad de disfrutar de la ciudad. Dos de los representantes de eBay mite la migración de aplicaciones .NET a la plataforma J2EE, y que cuenta con el apoyo del promotor de la plataforma .NET para Linux, Miguel de Icaza). Tuvimos ocasión de comentar por teléfono con Miguel desde EE.UU., y con el director de MainSoft, Yacoov Cohen, en Israel, que nos comentaron también la visión que tienen en Novell sobre los desarrollos para la plataforma .NET, y las implicaciones que prevén con la aparición de Windows Vista el próximo año. Y la traca final… El grupo de universitarios españoles, con Alberto Sánchez (primero de la derecha, de rodillas) << dotNetManía Los otros asistentes: los sponsors y fabricantes 20 En este apartado, pudimos apreciar un incremento de la presencia de fabricantes de productos de terceros, cuyas demos de producto, rozaban –a veces– el espectáculo, como cuando permitían que los usuarios se subieran a un Fórmula 1 conectado con un sistema de simulación por ordenador, y sintieran (con vibraciones incluidas), las sensaciones que se deben de sentir al conducir una de esas máquinas (sin peligro, eso sí). Pudimos comprobar el buen estado de salud de los productos estrella de Altova, Compuware, Oracle, HP, Borland, DevelopMentor, Sybari, Symantec, eBay, Infragistics, ScriptLogic (que nos presentó su nueva su nueva solución de administración de sistemas), Citrix (con cuyo representante en EMEA, Dave Austin, tuvimos ocasión de departir sobre la presentación de sus nuevos productos para la pequeña/mediana empresa) o MainSoft (curiosamente, esta empresa está popularizando un software –cuya demo nos mostraron en directo– que per- Como siempre, la traca final, con mucha gente, varios ambientes, buena música y comida europea (a buen entendedor…) puso el punto final de unas jornadas intensas, repletas de información, que sólo a la vuelta estamos empezando a digerir, y que refrescaremos con el invaluable DVD post-Tech-Ed, que incluye las grabaciones de todas las sesiones impartidas, y contribuye en buena medida a la sensación de evento de aprendizaje, ya que podemos analizar posteriormente cualquier sesión y reproducir su código fuente, como refuerzo de las ideas, o para asistir –llanamente– a lo que no pudimos ver por falta de tiempo. Conclusión Es difícil recoger en una única ubicación tanta actividad y tan gran número de expertos en tecnología, como la que se ha aglutinado en Ámsterdam este año. Hemos visto el futuro, con un nivel de aproximación a la realidad final más que notable. Hemos podido departir con gentes de intereses similares y hemos disfrutado de las capacidades de albergue que la capital de Holanda ofrece. Una ciudad que ha mostrado ya sobradamente su capacidad y buena disposición para albergar eventos de este tipo. El año próximo repetirá escenario (tercera edición consecutiva, como en Barcelona). Lo acogedor de la ciudad y su buen clima para esta época del año, le hacen un huésped idóneo para este tipo de eventos. Tech-Ed 2006 será sin duda el anticipo de Windows Vista (a punto de aparecer, y cuya presencia será sin duda la más destacada). Esperemos que en un futuro el evento retorne a España, tras los 3 años de rigor que, tradicionalmente, no se prolongan en una misma ciudad organizadora. dnm.plataforma.net Braulio Díez Reyes García Añadiendo nuestra aplicación al área de notificación Conseguir que nuestra aplicación apareciese en el área de notificación de Windows (como hace Messenger o una herramienta antivirus) no era tarea fácil con las herramientas de desarrollo antiguas. ¿Qué tal se porta .NET a la hora de implementar esta funcionalidad? << Lo primero de todo, ¿qué es el área de notificación? El área de notificación, en inglés llamado System Tray, es una parte de la barra de tareas de Windows que nos muestra los programas que tenemos corriendo en segundo plano y permite acceder a ellos rápidamente (ver figura 1). Figura 1. Área de notificación Reyes García Ha sido consultora “todo terreno”. Hoy día se dedica al gratificante mundo de la docencia. Braulio Díez colabora habitualmente con dotNetManía. Es MCSD en programación distribuida con Visual C++. Trabaja como Solutions Developer de Avanade. Me gustaría que mi aplicación estuviera disponible en dicha área, ¿cómo puedo añadir un icono que la represente?, ¿necesito convertirla a un servicio Windows?… Conforme avanzamos en este tema nos topamos con varios desafíos, en este artículo vamos a intentar resolverlos. Los puntos a tener en cuenta son los siguientes: • Añadir nuestra aplicación al área de notificación. • Distinguir entre cierre de ventana y cierre de sesión del usuario. • Arrancar nuestra aplicación al inicio de sesión del usuario sin mostrar la ventana principal de la misma. • Evitar que haya más de una instancia de nuestra aplicación ejecutándose a la vez. Esto lo iremos desgranando punto por punto. En www.dotnetmania.com se encuentra disponible una aplicación de ejemplo, realizada en C#, que le ayudará a seguirlos. ¡Manos a la obra! Añadir nuestra aplicación al área de notificación Gracias a .NET Framework ésta es la parte más sencilla de implementar. Los recursos que necesitamos son los siguientes: • Crear un proyecto “Aplicación Windows”. • Añadirle/crearle un icono que, por ejemplo, tendrá el nombre Notify.ico , y darle valor “Embedded Resource” a la propiedad “Build action”. • Asignar un menú de contexto a la ventana asociada al icono de notificación; a éste lo llamaremos Notifymenu. [ ] Servicios Windows Otra opción para implementar aplicaciones que corran en segundo plano es implementarlas como servicios Windows. Estos servicios están siempre corriendo aunque no haya usuario activo, si necesitamos darle un interfaz de ventanas tendremos que combinar el servicio con una aplicación estándar que podría ser activada vía remoting. .NET Framework incorpora soporte para crear servicios, pero esto queda fuera del objetivo de este artículo. << dnm.plataforma.net Normalmente las aplicaciones destinadas a ejecutarse en el área de notificación lo hacen mientras el usuario tenga su sesión activa, así pues, si intentamos cerrar la ventana principal lo que hace es minimizarse Ya sólo nos queda añadir el código, declarar el objeto de área de notificación e inicializarlo en el constructor de la ventana donde lo vayamos a usar (ver el fuente 1). public class mainForm : System.Windows.Forms.Form { (…) // Declaramos el objeto que manejara nuestra área de notificación. private NotifyIcon m_notifyIcon; (…) // Le asignamos el icono que queremos mostrar m_notifyIcon.Icon = new Icon(GetType(),”Notify.ico”); // Le asignamos el menú de contexto que hemos arrastrado a la ventana // principal, los eventos // del menú lo podemos enlazar con métodos directamente desde el editor // de la ventana // principal, como si de cualquier control se tratase. m_notifyIcon.ContextMenu = NotifyMenu; // También podemos enganchar eventos del Icono que se muestra // por ejemplo si pulsamos // doble click sobre él para que se muestre la ventana principal. m_notifyIcon.DoubleClick += new System.EventHandler(this.notifyIcon_DoubleClick); } // Doble click en nuestro icono del área de notificación: mostrar // la ventana... (Podemos hacer lo mismo con otros eventos) private void notifyIcon_DoubleClick(object sender, System.EventArgs e) { Show(); } } Fuente 1. Inicializando nuestro objeto de área de notificación Tras compilar y ejecutar la aplicación tendrá el aspecto que se ve en la figura 2. Sólo un pequeño detalle: cuando la cerramos, nuestro icono tar- Figura 2. Nuestra aplicación de ejemplo e icono de Notificación (Smily) da en desaparecer, esto lo podemos remediar sobrecargando el método Dispose de la ventana y liberando explícitamente nuestro objeto (ver el fuente 2). // Liberar recursos que estén en uso. protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } // Hacemos un dispose de nuestro objeto de //área de notificación. this.m_notifyIcon.Dispose(); } base.Dispose( disposing ); } Fuente 2. Liberando recursos <<dotNetManía // Constructor de nuestra ventana principal. public mainForm() { InitializeComponent(); // Inicializamos él objeto de área de notificación. m_notifyIcon = new NotifyIcon(); m_notifyIcon.Text = “DNM - Botón Derecho muestra menú”; m_notifyIcon.Visible = true; 23 << dnm.plataforma.net Distinguir entre cierre de ventana y cierre de sesión del usuario Normalmente las aplicaciones destinadas a ejecutarse en el área de notificación lo hacen mientras el usuario tenga su sesión activa, así pues, si intentamos cerrar la ventana principal lo que hace es minimizarse. Para poder cerrarla, o bien lo hacemos desde una opción del menú de contexto, o bien cuando el usuario cierra su sesión. En este último caso la aplicación lo detecta automáticamente y se cierra sola. Para poder distinguir entre cierre de sesión o cierre normal de ventana, tenemos que usar funciones nativas de Win32 y capturar el mensaje WM_QUERYENDSESSION (SystemEvents.SessionEnding no funciona cuando la ventana principal de nuestra aplicación se encuentra escondida). En el fuente 3 podemos ver cómo distinguir cada evento de cierre de aplicación. Para poder distinguir entre cierre de sesión o cierre normal de ventana, tenemos que usar funciones nativas de Win32 y capturar el mensaje WM_QUERYENDSESSION // Distinguir entre el cierre con el botón aspa de la ventana (minimizar), // o el cierre desde el menú de contexto o el cierre desde la sesión (cerrar // aplicación) private bool m_bRealClosing = false; (…) // Si recibimos el mensaje WM_QUERYENDSESSION el usuario está cerrando su sesión, // cerrar la aplicación. protected override void WndProc(ref Message m) { base.WndProc(ref m); // WM_QUERYENDSESSION if (m.Msg == 0x11) { ReallyCloseApplication(); } } // Si elegimos en el menú de contexto “Cerrar aplicación”. private void muClose_Click(object sender, System.EventArgs e) { ReallyCloseApplication(); } // Si cerramos desde el botón aspa de la ventana, esconder la ventana, si no // cerrar la aplicación. private void mainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if(!m_bRealClosing) { this.Hide(); e.Cancel = true; } } // Cerrar “de verdad” la aplicación. private void ReallyCloseApplication() { m_bRealClosing = true; if(this.m_FormAlreadyLoaded) { Close(); } else { // Hacemos un dispose de nuestro objeto de área de notificación. this.m_notifyIcon.Dispose(); } // Nos salimos de la aplicación (hay que tener en cuenta que la app no tiene // asociada una ventana principal. Application.Exit(); } <<dotNetManía Arrancar la aplicación cuando se inicie la sesión y no mostrar la ventana 24 Para que una aplicación arranque cuando se inicie la sesión de usuario es necesario añadir una entrada a las siguientes direcciones del registro: Fuente 3. Cerrando la aplicación HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ Windows\CurrentVersion\Run HKEY_CURRENT_USER\SOFTWARE\Microsoft\ Windows\CurrentVersion\Run Con la primera conseguimos que la aplicación se ejecute para cualquier usuario que arranque la máquina, la segunda es para el usuario que tenga activa la sesión en ese momento. En dicha entra- << dnm.plataforma.net da le indicaremos el nombre de nuestra aplicación y el path completo donde podemos encontrarla. El fragmento de código que realiza esta función se puede encontrar en la aplicación de ejemplo (método NotifyHelper. RunApplicationOnSessionStartup). Otro punto a tener en cuenta es que la aplicación se arranque automáticamente de forma “silenciosa”, es decir, que muestre el icono de notificación pero no la ventana principal, para ello modificamos el “main” de la aplicación (ver el fuente 4). [STAThread] static void Main() { // La siguiente es la línea de código que hemos // sustituido: // // Application.Run(new mainForm()); // // Creamos el mainForm (el constructor muestra el // icono en el área de notificación). mainForm mainform = new mainForm(); // En vez de mostrar la ventana, directamente // dejamos correr la aplicación. Application.Run(); } Fuente 4.Arrancar la aplicación en modo “silencioso” Permitir sólo una instancia de nuestra aplicación corriendo a la vez Por último, no podemos olvidarnos de que la mayoría de aplicaciones de este tipo no suelen permitir que haya más de una instancia de la misma corriendo a la vez, esto lo controlamos usando el objeto de sincronización del sistema operativo, un mutex local con nombre. Cuando se arranca la aplicación intentamos apropiarnos de dicho mutex, si ya hay una aplicación del mismo tipo corriendo, la [STAThread] static void Main() { // __UniqueMutexAppName es sólo un string que contiene // un nombre único, e.g. “MiAplicacion_GUID” if(!NotifyHelper.IsOtherInstanceOfTheAppAlreadyRunning( GlobalConstantsValues.__UniqueMutexAppName)) { mainForm mainform = new mainForm(); Application.Run(); } } Fuente 5. Comprobando que no hay otra instancia de la aplicación corriendo static public bool IsOtherInstanceOfTheAppAlreadyRunning( string uniqueName) { bool firstInstance; // Si podemos reservar el mutex, no hay más instancias de // la aplicación corriendo. _SingleAppInstanceMutex = new Mutex(false, “Local\\” + uniqueName, out firstInstance); // No debemos liberar el mutex, cuando la aplicación se cierre, // este será liberado automáticamente. return !firstInstance; } Fuente 6. Comprobación con el Mutex Para saber más Si quiere ampliar información acerca de este tema, aquí tiene unos enlaces que le pueden ser de interés: “Adding tray icons and context menus” http://www.codeproject.com/csharp/trayiconmenu01.asp “Making a Windows Forms app respond to System Shutdown” http://www.stevex.org/dottext/articles/155.aspx “Making a startup Window Form Invisible” http://msdn.microsoft.com/library/default.asp?url=/library/enus/vbcon/html/vbtsksettingformtobeinvisibleatitsinception.asp “Adding your application to the Windows Startup” http://www.codeproject.com/system/windows_startup.asp “More about single instance Mutex” http://www.yoda.arachsys.com/csharp/faq/#one.application.instance <<dotNetManía ...la mayoría de aplicaciones de este tipo no suelen permitir que haya más de una instancia de la misma corriendo a la vez, esto lo controlamos usando el objeto de sincronización del sistema operativo, un mutex local con nombre apropiación fallará y cerraremos la aplicación (ver el fuente 5 y 6). 25 dnm.plataforma.net Carlos Quintero El modelo de objetos de Visual Studio .NET Muchas de las tareas que realizamos a mano en Visual Studio .NET se pueden automatizar mediante macros y muchas otras se pueden mejorar o extender mediante complementos.En este artículo veremos el modelo de objetos que proporciona Visual Studio .NET para poder manejar el propio entorno de desarrollo desde código. << En el número 16 del mes de junio hablamos de la creación de complementos (add-ins) para Visual Studio, centrándonos solamente en proporcionar la infraestructura de comandos, barras de herramientas, menús y botones de nuestro complemento. En este artículo profundizaremos en el modelo de objetos que nos proporciona el entorno de desarrollo de Visual Studio .NET 2002/2003 para su automatización. Este modelo de objetos reside en el ensamblado EnvDTE.dll, que nos proporciona el espacio de nombres EnvDTE (podemos explorar este modelo mediante el examinador de objetos). La clase raíz del modelo es DTE, que son las siglas de Development Tools Environment y representa el entorno de desarrollo. Una instancia de dicha clase nos dará acceso a las ventanas, archivos, documentos, etc. de Visual Studio .NET. La manera de obtener una instancia de dicha clase depende de cómo estemos automatizando el entorno de desarrollo: • Usando el editor de macros (menú “Herramientas”, “IDE de macros…”), existe una instancia implícita con el nombre DTE. Por ejemplo, la siguiente macro muestra el nombre y la versión del entorno de desarrollo: Carlos J. Quintero es Microsoft MVP de .NET desde principios del año 2004. Es autor del popular complemento MZTools 3.0 para VB6,VB5 y VBA, y de MZ-Tools 4.0 para Visual Studio .NET 2002/ 2003, ambos disponibles en http://www.mztools.com Sub Macro1() MessageBox.Show(DTE.Name & " " & DTE.Version) End Sub • Usando un complemento, el método OnConnection recibe en el parámetro Application dicha instancia. Como se recibe del tipo Object , debemos convertirla al tipo EnvDTE.DTE. La variable usada por el asistente de complementos es applicationObject, por lo que ésta es la instrucción que veremos siempre en dicho método: applicationObject = CType(application, EnvDTE.DTE) • Usando un programa externo al propio Visual Studio .NET, por ejemplo un archivo VBScript, se puede crear una instancia de la clase DTE mediante los ProgID “VisualStudio.DTE.7.1” para Visual Studio .NET 2003 y “VisualStudio.DTE.7” para Visual Studio .NET 2002, o bien “VisualStudio.DTE” para usar la versión más alta de las que haya instaladas. Aquí se muestra un script en lenguaje VBScript que abre una instancia de Visual Studio .NET, la hace visible, muestra su nombre y versión y la cierra: Dim objDTE Set objDTE = CreateObject("VisualStudio.DTE") objDTE.MainWindow.Visible = True MsgBox objDTE.Name & " " & objDTE.Version objDTE.Quit Con cualquiera de estos métodos tendremos una instancia de la clase DTE y ya podremos empezar a “jugar” con ella. En los siguientes apartados veremos cómo manejar por código las soluciones, proyectos, archivos y ventanas del entorno de desarrollo, cómo editar el texto de nuestros documentos de código y cómo obtener información sobre sus elementos de código (clases, procedimientos, parámetros, etc.) ¡sin tener que “parsear” el documento! << dnm.plataforma.net Como sabemos, una solución es un conjunto de proyectos relacionados y éstos a su vez se componen de referencias y archivos. Para manejar una solución disponemos de la clase EnvDTE.Solution, que se obtiene a partir del objeto DTE mediante su propiedad Solution. Para manejar los proyectos disponemos de la case EnvDTE.Project, y podemos obtener los proyectos de una solución mediante la colección Solution.Projects. Para manejar los archivos disponemos de la clase EnvDTE.ProjectItem y los archivos de un proyecto se obtienen mediante la colección Project.ProjectItems. En este punto hay que indicar que un ProjectItem no siempre es un archivo, también puede ser una carpeta y que un archivo puede tener a su vez otros archivos relacionados. Por ejemplo, las páginas ASPX tienen archivos de código por detrás, y los archivos de formularios tienen archivos .RESX relacionados. Para tratar ambos casos, la clase EnvDTE.ProjectItem proporciona una colección ProjectItem.ProjectItems, la cual tiene a su vez una propiedad ProjectItems.Parent para poder realizar la navegación por la jerarquía en orden ascendente. Finalmente, cualquier ProjectItem tiene una propiedad ProjectItem.ContainingProject para poder saber cuál es su proyecto padre. Con todo esto podemos obtener la jerarquía de proyectos y archivos de nuestra solución, y obtener las propiedades de cada elemento, como veremos más adelante. Pero antes veamos cómo obtener información sobre las referencias de un proyecto. Si examinamos la clase EnvDTE.Project veremos que no hay ninguna colección para obtener las referencias de un proyecto. Esto es así porque no todos los tipos de proyecto usan referencias (por ejemplo, los proyectos de instalación). Para proporcionar acceso a propiedades y métodos específicos de un tipo de proyecto existe la propiedad Project.Object, que devuelve un tipo System.Object que ha de ser convertido a un tipo específico del tipo de proyecto. En el caso de C# y VB.NET, este tipo es VSLangProj.VSProject, que está definido en el ensamblado VSLangProj.dll, separado del ensamblado EnvDTE.dll y que por tanto habrá que añadir separadamen- Sub MacroInformacionSolucion() Dim objProject As EnvDTE.Project Dim objVSProject As VSLangProj.VSProject Dim objReference As VSLangProj.Reference Try If DTE.Solution.IsOpen() Then ' Muestra las propiedades de la solución Debug.WriteLine("Nombre completo de la solución: " & DTE.Solution.FullName) MostrarPropiedades(DTE.Solution.Properties) ' Muestra los proyectos For Each objProject In DTE.Solution.Projects Debug.WriteLine("Nombre completo del proyecto: " & objProject.FullName) Debug.WriteLine("Nombre del proyecto: " & objProject.Name) Debug.WriteLine("Nombre único del proyecto: " & objProject.UniqueName) MostrarPropiedades(objProject.Properties) MostrarProjectItems(objProject.ProjectItems) If TypeOf objProject.Object Is VSLangProj.VSProject Then objVSProject = DirectCast(objProject.Object, VSLangProj.VSProject) For Each objReference In objVSProject.References() Debug.WriteLine("Referencia " & objReference.Identity) Next End If Next End If Catch objException As Exception MessageBox.Show(objException.ToString) End Try End Sub Sub MostrarPropiedades(ByVal colProperties As EnvDTE.Properties) Dim objProperty As EnvDTE.Property Dim objValue As Object For Each objProperty In colProperties Try objValue = objProperty.Value Catch objValue = Nothing End Try If objValue Is Nothing Then Debug.WriteLine(objProperty.Name & ": <vacío>") Else Debug.WriteLine(objProperty.Name & ": " & objValue.ToString) End If Next End Sub Sub MostrarProjectItems(ByVal colProjectItems As EnvDTE.ProjectItems) Dim objProjectItem As ProjectItem For Each objProjectItem In colProjectItems MostrarPropiedades(objProjectItem.Properties) ' Entra en recursión MostrarProjectItems(objProjectItem.ProjectItems) Next End Sub Fuente 1 <<dotNetManía Soluciones, proyectos y archivos 27 << dnm.plataforma.net <<dotNetManía También podemos crear soluciones mediante automatización,añadir proyectos a una solución y añadir archivos o referencias a un proyecto 28 te. Una vez que hemos convertido Project.Object a VSLangProj.VSProject, esta clase sí contiene una colección VSProject.References para obtener las referencias de un proyecto. La macro del fuente 1 hace uso de todo lo explicado y obtiene información de la solución y sus proyectos, archivos y referencias. Conviene indicar que algunas de las propiedades de los objetos del modelo de extensibilidad son de tipo String y no un valor enumerado como cabría esperar. Esto es así porque siendo Visual Studio .NET tan extensible que permite albergar nuevos lenguajes de programación o nuevos tipos de proyecto, no se pueden acotar los valores que puede tomar una propiedad. Muchos de los valores conocidos de dichas constantes están disponibles en la clase EnvDTE.Constants o en clases del ensamblado VSLangProj (para proyectos VB.NET y C#) como las clases VSLangProj.PrjKind (para saber el lenguaje de un proyecto), VSLangProj.prjOutputType (para saber el tipo de proyecto), etc. También podemos crear soluciones mediante automatización, añadir proyectos a una solución y añadir archivos o referencias a un proyecto. Esto es muy útil si deseamos construir una especie de asistente que cree el esqueleto de una aplicación conforme a los estándares de proyectos de nuestra empresa. Las soluciones se pueden crear mediante el método Solution.Create, se pueden guardar mediante el método Solution.SaveAs y se pueden volver a abrir mediante el método Solution.Open. Para añadir proyectos a una solución podemos usar o bien el método Solution.AddFromFile (para añadir proyectos que ya están creados) o bien el método Solution.AddFromTemplate (para añadir proyectos nuevos). Para añadir archivos y carpetas a un proyecto tenemos a nuestra disposición varios métodos como ProjectItems.AddFolder (para crear carpetas nuevas), ProjectItems.AddFromDirectory (para añadir todos los archivos que se encuentren en una carpeta), ProjectItems.AddFromFile (para añadir un archivo existente que se deja en su carpeta y se referencia desde ahí), ProjectItems.AddFromFileCopy (para añadir un archivo existente que se copia a la carpeta de destino antes de ser añadido) y ProjectItems.AddFromTemplate (para añadir archivos nuevos). Para añadir referencias a un proyecto tenemos que hacerlo a través de la colección VSLangProj.References que vimos anteriormente. Esta colección proporciona los métodos References.Add (para añadir una referencia a un ensamblado .NET), References.AddActiveX (para añadir una referencia a un componente COM) y References.AddProject (para añadir una referencia a otro proyecto de nuestra solución). Ventanas Para manejar ventanas el modelo de extensibilidad nos proporciona la clase EnvDTE.Window. Básicamente Visual Studio .NET proporciona 3 tipos de ventanas: • La ventana principal del IDE, que se obtiene mediante la propiedad DTE.MainWindow. • Las ventanas de documentos. • Las ventanas de herramientas (ToolWindows), como el explorador de soluciones, la lista de tareas, la ventana de propiedades, etc. La propiedad DTE.ActiveWindow devuelve la ventana activa del IDE. Se puede acceder a todas las ventanas mediante la colección DTE.Windows, que podemos iterar en busca de una ventana en particular. Para ventanas de herramientas es más óptimo buscar con índices únicos proporcionados por las constantes de EnvDTE.Constants.vsWindowKindXXX. Muchas de las ventanas del IDE proporcionan un modelo de objetos que permite manipular su contenido. Para ello, las ventanas proporcionan una propiedad Window.Object que puede ser convertida al tipo adecuado de dicha ventana. Por ejemplo, la macro del fuente 2 obtiene la ventana de la lista de tareas y muestra las tareas de la lista. Sub ObtieneListaTareas() Dim objWindow As EnvDTE.Window Dim objTaskList As EnvDTE.TaskList Dim objTaskItem As EnvDTE.TaskItem objWindow = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindTaskList) objTaskList = DirectCast(objWindow.Object, EnvDTE.TaskList) For Each objTaskItem In objTaskList.TaskItems Debug.WriteLine(objTaskItem.Description) Next End Sub Fuente 2 Las propiedades como Window.Object devuelven un objeto del tipo _ComObject, así que ¿cómo se puede saber el tipo del espacio de nombres EnvDTE al que tenemos que convertirlas? La respuesta viene de la mano de una función poco conocida: << dnm.plataforma.net El modelo de código de Visual Studio .NET permite descubrir los elementos de nuestros archivos de código mos abrir (EnvDTE.Constants.vsViewKindDesigner, EnvDTE.Constants.vsViewKindCode, etc). Dicho método devuelve un objeto DTE.Window, cuyo documento podemos obtener con la propiedad Window.Document. Se pueden guardar los cambios de un documento con el método Document.Save y se puede cerrar un documento con el método Document.Close, que nos permite indicar en un parámetro si hay que guardar los cambios o no. Edición de texto Para los documentos que son de texto, la llamada devuelto “TaskList”. Otros tipos comunes que encontraremos en la propiedad Window.Object son: • EnvDTE.UIHierarchy. Permite navegar la jerarquía del explorador de soluciones, del explorador de servidores y del explorador de macros, aunque no de la vista de clases). • EnvDTE.ToolBox. Para la ventana de la caja de herramientas) • System.ComponentModel.Design.IDesignerHost. Para diseñadores de formularios. • EnvDTE.TextWindow. Para ventanas de texto. • EnvDTE.HTMLWindow. Para diseñadores HTML. Con esas clases podremos descubrir y manipular el contenido de sus respectivas ventanas. Documentos Como hemos visto hasta ahora, un ProjectItem es un archivo en disco, y una ventana es un elemento de la interfaz de usuario que, en el caso de archivos, nos permite editar su contenido. Entre ambos existe una entidad intermedia que es el documento. El documento proporciona un buffer editable que se mantiene en memoria hasta que se cierra, permitiendo guardar los cambios en disco en cualquier momento. Para manejar documentos tenemos las clases EnvDTE.Document (para documentos en general) y EnvDTE.TextDocument (para documentos de texto). El IDE nos proporciona la lista de documentos en la colección DTE.Documents, y el documento activo en la propiedad DTE.ActiveDocument. La relación de un documento con su ProjectItem es de uno a uno (propiedad Document.ProjectItem), pero un documento puede estar abierto en varias ventanas, por ejemplo, el documento Form1.vb puede tener abierta una ventana de código y una ventana con el diseñador de formularios. La propiedad Document.Windows nos devuelve las ventanas de un documento y la propiedad Document.ActiveWindow nos devuelve la ventana activa del documento. Para abrir un documento a partir de un ProjectItem se usa el método ProjectItem.Open, que recibe como parámetro el tipo de ventana que quere- dos más importantes de esta clase están relacionados con los objetos EnvDTE.TextPoint, EnvDTE.EditPoint y EnvDTE.TextSelection. Los dos primeros representan posiciones en el documento de texto, con propiedades como TextPoint.Line para obtener el número de línea y TextPoint.LineCharOffset para obtener la columna. La diferencia entre ambos es que el TextPoint no es editable, mientras que el EditPoint sí lo es. Se puede obtener un EditPoint a partir de un TextPoint mediante el método TextPoint.CreateEditPoint. La macro del fuente 3 muestra cómo insertar un texto en la cabecera del documento de texto activo. Sub InsertarEncabezado() Dim objTextDocument As EnvDTE.TextDocument Dim sTexto As String If Not (DTE.ActiveDocument Is Nothing) Then Try objTextDocument = DTE.ActiveDocument.Object("TextDocument") Catch End Try If Not (objTextDocument Is Nothing) Then objTextDocument.StartPoint.CreateEditPoint.Insert("' Archivo " &_ DTE.ActiveDocument.Name & Microsoft.VisualBasic.ControlChars.CrLf) End If End If End Sub Fuente 3 El explorador de macros contiene un proyecto de ejemplo con multitud de macros que nos servirán para conocer todo lo relativo a la edición de código fuente. El modelo de código El modelo de código de Visual Studio .NET permite descubrir los elementos (clases, propiedades, procedimientos, parámetros, atributos, etc.) de nuestros archi- <<dotNetManía Microsoft.VisualBasic.Information.TypeName(objeto). Para el caso de la macro anterior, nos habría Document.Object("") o Document.Object("TextDocument") nos devuelve un objeto EnvDTE.TextDocument. Los méto- 29 << dnm.plataforma.net vos de código. La clase central para este cometido es EnvDTE.CodeElement, cuya propiedad CodeElement.Kind nos devuelve el tipo de elemento. A su vez, un objeto de la clase EnvDTE.CodeElement se puede convertir a un tipo específico acorde con su tipo que proporciona funciones y métodos que son sólo aplicables a ese tipo de elemento de código (por ejemplo, EnvDTE.CodeNamespace, EnvDTE.CodeClass, etc). En C++ existen muchos tipos de elementos (y de hecho C++ usa un modelo de código distinto), pero en VB.NET y C# los elementos de código que tenemos se muestran en la tabla 1. Hay que señalar que existe una clase EnvDTE.CodeType para manejar de forma unificada los elementos de código que son tipos (clases, estructuras, interfaces, delegados y enums). Para navegar por los elementos de código de un archivo usaremos la propiedad ProjectItem.FileCodeModel, y para un proyecto usaremos Project.CodeModel. En ambos casos el objeto devuelto tiene una propiedad CodeElements que nos devuelve la colección de elementos raíz. Para obtener los elementos de código hijos de Elemento de código Propiedad Kind Sub MostrarElementosDeCodigo() Dim objProjectItem As ProjectItem If Not (DTE.ActiveDocument Is Nothing) Then objProjectItem = DTE.ActiveDocument.ProjectItem If Not (objProjectItem.FileCodeModel Is Nothing) Then MostrarElementosDeCodigoRecursivo(objProjectItem.FileCodeModel.CodeElements, 0) End If End If End Sub Sub MostrarElementosDeCodigoRecursivo(ByVal colCodeElements As CodeElements, _ ByVal iNivel As Integer) Dim objCodeElement As EnvDTE.CodeElement Dim colMembers As EnvDTE.CodeElements For Each objCodeElement In colCodeElements Debug.WriteLine(New String(" "c, iNivel * 3) & objCodeElement.Name) colMembers = ObtenerHijos(objCodeElement) If Not (colMembers Is Nothing) Then MostrarElementosDeCodigoRecursivo(colMembers, iNivel + 1) End If Next End Sub Private Function ObtenerHijos(ByVal objCodeElement As CodeElement) As CodeElements Dim colCodeElements As CodeElements If TypeOf objCodeElement Is CodeNamespace Then colCodeElements = DirectCast(objCodeElement, CodeNamespace).Members ElseIf TypeOf objCodeElement Is CodeType Then colCodeElements = DirectCast(objCodeElement, CodeType).Members End If Return colCodeElements End Function Fuente 4 Tipo propio Espacio de nombres vsCMElementNamespace EnvDTE.CodeNamespace Clase vsCMElementClass EnvDTE.CodeClass Estructura vsCMElementStruct EnvDTE.CodeStruct Enum vsCMElementEnum EnvDTE.CodeEnum Interface vsCMElementInterface EnvDTE.CodeInterface Delegado vsCMElementDelegate EnvDTE.CodeDelegate Propiedad vsCMElementProperty EnvDTE.CodeProperty Procedimiento vsCMElementFunction EnvDTE.CodeFunction Variable vsCMElementVariable EnvDTE.CodeVariable ría. Para ello, diversas clases disponen de métodos que comienzan con “Add”. Por ejemplo, tenemos FileCode Model.AddNamespace, FileCodeModel.Add Class, CodeClass.Add Function, CodeFunc tion.AddParameter, <<dotNetManía etc. La mala noticia es que muchos de Parámetro vsCMElementParameter EnvDTE.CodeParameter estos métodos no Atributo vsCMElementAttribute EnvDTE.CodeAttribute están implementados para todos los Tabla 1 lenguajes, de manera que es posible que un CodeElement es necesario usar el tipo un método funcione con C# pero no con propio de cada elemento de código: VB.NET o viceversa. En cualquier caso CodeNamespace.Members, CodeClass.Mem siempre podemos construir por nosotros bers, etc. (curiosamente la propiedad mismos el párrafo de texto con el elemento CodeElement.Children que intuitivamende código que queremos agregar y usar la te sería la que emplearíamos no funciofunción EditPoint.Insert como se explinaría, ya que sólo vale para C++). La macro có en un apartado anterior. del fuente 4 recorre los elementos de códiY con esto terminamos este artígo del documento de código activo. culo. Naturalmente se han quedado El modelo de código también permialgunas cosas en el tintero, porque la te generar código fuente, al menos en teoextensibilidad de Visual Studio .NET 30 da para escribir libros enteros (o al menos unos cuantos capítulos), pero se han tratado los aspectos fundamentales. En un par de meses estará disponible Visual Studio 2005, que promete mejorar e introducir novedades en el modelo de extensibilidad para hacernos la vida más fácil. Documentación La documentación de referencia imprescindible para entender el modelo de extensibilidad de Visual Studio .NET es la siguiente: [1] Manipulating the Development Environment: http://msdn.microsoft.com /library/default.asp?url=/library/enus/vsintro7/html/vxoriManipulatingDev elopmentEnvironment.asp [2] Automation and Extensibility Reference: http://msdn.microsoft.com/ library/default.asp?url=/library/en-us/ vsintro7/html/vxoriExtensibilityRefere nce.asp [3] Libro “Inside Microsoft Visual Studio .NET 2003”, de Craig Skibo y otros: http://www.microsoft.com/mspress/books/ 6425.asp dnm.inicio.fundamentos dnm.incio.taller Guillermo “Guille” Som Interfaces En el artículo sobre las interfaces de dnm.inicio.fundamentos publicado en el nº 16 de dotNetManía,explicamos lo que son las interfaces y vimos algunos ejemplos de cómo usarlas.En esta ocasión veremos más ejemplos,con idea de que nos quede claro cómo utilizar las interfaces en nuestros proyectos, aunque en esta ocasión vamos a usar las interfaces de una forma diferente a lo “habitual”, con la intención de que nos hagamos una idea de lo útiles que pueden llegar a ser estos tipos de datos. << Usar las interfaces como parámetro de métodos Guillermo “Guille” Som es Microsoft MVP de Visual Basic desde 1997. Es redactor de dotNetManía, miembro de Ineta Speakers Bureau Latin America, mentor de Solid Quality Learning Iberoamérica y autor del libro Manual Imprescindible de Visual Basic .NET. http://www.elguille.info Las interfaces no las vamos a utilizar siempre desde la perspectiva de ofrecer funcionalidades “compatibles” con las clases de .NET Framework, ni con otras de nuestra propia cosecha, al menos desde el punto de vista de que al implementar alguna interfaz, nuestra clase tenga la “funcionalidad” aportada por dicha interfaz. Por ejemplo, si necesitamos pasar parámetros a distintos métodos, pero no sólo nos interesa indicar el contenido de unas cadenas o unos valores numéricos, sino que también queremos pasar algo de “acción”, es decir, algún método que actúe sobre esos parámetros o sobre los valores que internamente el método tenga que usar..., en estos casos también nos puede interesar utilizar las interfaces, ya que éstas nos proporcionan una forma de utilizar objetos anónimos (o previamente indefinidos), los cuales dejarán el anonimato en el momento que nuestro código ejecute dicho método. Aclaremos un poco todo esto para que nos entendamos mejor: Si tenemos un método declarado de esta forma: Para VB: Metodo(parámetro As Interfaz) Para C#: Metodo(Interfaz parámetro) Es obvio que parámetro es del tipo de una interfaz, por tanto, el argumento real que pasaremos a este método será de un objeto que implemente la interfaz indicada en el tipo del parámetro. Esa interfaz tendrá cierta funcionalidad y posiblemente algunas propiedades. Todo eso lo podemos usar en ese método sin importarnos qué objeto es el que utilizamos a la hora de llamarlo, o para decirlo de otra forma: sin importarnos de qué tipo es el objeto pasado como argumento. Si usamos las interfaces de esta forma, realmente los tipos que la implementen no lo harán para tener la funcionalidad de la interfaz, (aunque también), sino porque así podrán usarse en otros contextos. En el fondo es lo mismo, aunque al usarlas de este modo ampliamos la forma de aprovecharnos de las interfaces y de la filosofía de las mismas: proporcionar funcionalidad anónima y proveer de polimorfismo a nuestras clases y estructuras. Dos ejemplos de interfaces como parámetros A continuación veremos un par de ejemplos en los que utilizaremos esta otra forma de darle utilidad a las interfaces. El primer ejemplo ya lo vimos en el nº 7 de dotNetManía (pág. 24), en el que usábamos una clase específica para clasificar tipos que no estaban “preparados” para ser clasificados, (no vamos a entrar en detalles sobre cómo hacer una clase que pueda ser clasificada, ya que de eso nos ocupamos en el citado número de dotNetManía.) El caso era que teníamos una clase “normal” que no estaba preparada para ser clasificada por el propio .NET, es decir, no implementaba la interfaz IComparable. Pero queríamos clasificar el contenido de una colección que contenía objetos de ese tipo no clasificable. La solución fue usar una de las sobrecargas del método Sort, al que se le pasa como argumento una clase que implemente una interfaz (IComparer). La clase pasada como argumento tiene que implementar dicha interfaz, y se encargará de clasificar (o comparar) dos elementos de un tipo determinado. << dnm.inicio.taller a basar en una interfaz que podemos implementar en nuestros formularios. La razón de hacer esto es porque algunas veces nos podemos encontrar con la situación de que queremos dar cierta funcionalidad a nuestros formularios, pero puede que esa nueva funcionalidad sea diferente en cada uno de ellos. Una de las formas de proporcionar ese nuevo funcionamiento es crear una clase basada en la clase Windows.Forms.Form, (que es la clase base de cualquier formulario de .NET), y añadirle la nueva funcionalidad con elementos (miembros) virtuales (reemplazables). Después, sólo tendríamos que crear nuevos formularios basados en esa clase y así dispondríamos de todas las nuevas características añadidas en nuestra clase base. Pero es posible que la implementación (el código a usar) de esa nueva funcionalidad sea diferente dependiendo de lo que queramos que nuestro formulario haga, por tanto, no tiene mucho sentido escribir un código que después lo vamos a reemplazar en la mayoría de las veces que usemos esa clase. En este tipo de situaciones es donde nos podemos beneficiar del uso de las interfaces, ya que una interfaz no tiene código ejecutable, solamente define los miembros que tenemos que implemen- [ ] NOTA Como ya sabemos las clases que implementan una interfaz solamente están obligadas a definir los miembros de esa interfaz, pero no hay nada que nos obligue a escribir código dentro de esos miembros. Por supuesto, implementar una interfaz para después no darle “funcionalidad” no tiene mucho sentido, pero es conveniente saber que el compilador no chequeará que esos miembros realmente hagan algo. En el fuente 1 tenemos el código para C#1 de la clase “intermedia” que podemos usar para clasificar objetos de un tipo que no implementa la interfaz IComparable. De esta clase sólo usaremos la parte expuesta por la interfaz IComparer, es decir, el método Compare; si esta clase tuviera más miembros, éstos se ignorarán, al menos al usar el objeto como argumento del método Sort. public class ColegaComparer : IComparer { public int Compare(object x, object y) { Colega c1 = ((Colega)x); Colega c2 = ((Colega)y); return string.Compare(c1.Apellidos, c2.Apellidos); } } Fuente 1. Código de la clase que implementa la interfaz IComparer Pero no solo tenemos que usar interfaces definidas en el propio .NET Framework, ya que las interfaces usadas pueden ser de cualquier tipo, lo importante aquí es que el método al que queremos pasar un objeto acepte un tipo de interfaz, y, como es lógico suponer, el objeto pasado debe implementar esa interfaz. El segundo ejemplo que usaremos para pasar interfaces a métodos, lo vamos 1 tar, y cada implementación puede ser diferente unas de otras porque lo único importante es que (en nuestro caso) el formulario implemente esos miembros y le de la funcionalidad que creamos conveniente. Por ejemplo, puede ser que queramos crear un formulario para realizar búsquedas, y queremos que no dependa de ningún formulario en particular. Por tanto lo podemos usar con formularios que utili- cen diferentes tipos de controles para almacenar la información en la que realizaremos la búsqueda. Para darle esa independencia al formulario que pedirá los datos que queremos buscar, podemos utilizar una interfaz que defina los miembros que cada formulario tendrá que implementar, de forma que nuestro formulario de buscar utilice la parte del formulario que implementa la interfaz para llamar a los métodos. Ni qué decir tiene que ese formulario de búsqueda no será el encargado de buscar nada, ya que no sabe dónde tendrá que realizar dicha búsqueda, por tanto serán los formularios que implementen la interfaz los que se encarguen de todo el trabajo. En la figura 1 tenemos el formulario buscar. En el control combo estarán las últimas palabras usadas en las búsquedas anteriores. Figura 1. El formulario buscar en tiempo de diseño. En el fuente 2 tenemos la definición de la interfaz IBuscar que además de un método Buscar al que se le pasará como argumento la palabra que hay que buscar, también define dos métodos: • LeerCfg devuelve un array con las palabras usadas en búsquedas anteriores • GuardarCfg tiene un parámetro en el que se indicará la palabra buscada en la última ocasión. En el formulario buscar hemos definido un método Show que se usará para mostrarlo y al que habrá que indicarle un objeto que implemente la interfaz IBuscar. Ese argumento se asignará a una variable interna del tipo de la interfaz, con idea de usarla para llamar a los métodos correspondientes del objeto pasado. Lo primero que hacemos, después de asignar el objeto recibido a la variable interna, es llamar al método En el texto sólo aparecen los fuentes en C# pero puede descargarse también los de VB.NET desde nuestra Web www.dotnetmania.com <<dotNetManía Al estar declarado el parámetro como un tipo concreto de una interfaz, esa sobrecarga del método Sort se asegura de que el objeto usado como argumento tiene la funcionalidad que se espera, por tanto, será seguro usarlo, y se supone que hará el trabajo que debe hacer. 33 << dnm.inicio.taller // Interfaz para proporcionar métodos para buscar public interface IBuscar { string[] LeerCfg(); void GuardarCfg( string palabra); bool Buscar( string texto); } // El formulario de buscar private IBuscar elForm; public void Show(IBuscar formulario) { elForm = formulario; // leemos los datos de la configuración string[] lista = elForm.LeerCfg(); cboBuscar.Items.Clear(); if( lista == null ) cboBuscar.Text = ""; else { foreach( string s in lista) cboBuscar.Items.Add(s); cboBuscar.SelectedIndex = 0; } // this.Show(); } <<dotNetManía private void btnAceptar_Click(object sender, EventArgs e) { // Llamamos al formulario para que busque el texto // y si lo encuentra cerramos este formm en caso // contrario damos la oportunidad de buscar otra cosa if( elForm.Buscar(cboBuscar.Text) ) { // Llamamos al método guardarCfg // por si quiere guardar la palabra buscada elForm.GuardarCfg(cboBuscar.Text); Hide(); } else cboBuscar.Focus(); } 34 public class Form1 : System.Windows.Forms.Form, IBuscar { public bool Buscar(string texto) { // Realizar una búsqueda en el contenido del textbox // Devolverá True si ha encontrado lo buscado, // y se encargará de resaltar el texto, etc. int pos = RichTextBox1.Find(texto); if( pos > -1 ) RichTextBox1.Select(pos, texto.Length); return pos > -1; } public void GuardarCfg(string palabra) { // El código para guardar la configuración en este formulario // El parámetro será la palabra que se ha indicado en buscar // Tendremos que decidir si la guardamos o que... } public String[] LeerCfg() { // El código para leer la configuración en este formulario // y devolverla como un array de tipo String return new String[] {"Porque", "no engraso", "los ejes", "me llaman", "abandonao", "gustan", "suenen"}; } private void btnBuscar_Click(object sender, EventArgs e) { // Mostrar el formulario de búsqueda FormBuscar fBuscar = new FormBuscar(); fBuscar.Show(this); } Fuente 3. Código del formulario que implementa la interfaz. go en los métodos definidos por la interfaz, y tal como veremos en el código implementado en private void btnCancelar_Click(object sender, EventArgs e) el formulario que usa { IBuscar, no se hace nada Hide(); en el método GuardarCfg, } pero como las interfaces Fuente 2. Código de la interfaz y el formulario buscar “obligan” a que tengamos que implementar LeerCfg para asignar al combo las palatodos los miembros definidos en ellas, bras usadas con anterioridad. estaremos obligados a crear al menos el Cuando el usuario pulsa en el botón cuerpo del método para que nuestro “Aceptar”, se llama al método Buscar de código compile. la interfaz, y si devuelve un valor verLa aplicación de ejemplo utiliza dos dadero querrá decir que el texto indiformularios que implementan la interfaz cado ha sido hallado, por tanto llamaIBuscar: en uno de ellos se utiliza un conmos al método GuardarCfg para que el trol RichTextBox y en el otro un control formulario sepa que esa es la palabra que TextBox. Para buscar en el primero utilidebe añadir a su lista de palabras interzamos el método Find, mientras que en el nas. En caso de que devuelva un valor segundo llamamos al método IndexOf de falso, se sigue mostrando el formulario la propiedad Text de la caja de textos. Esto de búsqueda hasta que se encuentre algo simplemente es para que veamos que realo se cancele. mente al código del formulario buscar le Tal como comentamos en la nota, da igual qué tipo de control será el que se no tenemos por qué implementar códiuse para hacer la búsqueda, ya que será el propio formulario el que se encargará de hacer esa búsqueda. En el fuente 3 tenemos las implementaciones de los tres métodos de la interfaz IBuscar, además del método que muestra el formulario de búsqueda, al que hay que indicarle como argumento la instancia actual del formulario, aunque ese objeto se “filtrará” para dejar pasar sólo la parte del mismo que implementa la interfaz. Esperamos que con lo aquí mostrado tengamos otra visión de cómo usar las interfaces, pero esto no lo es todo, en otra ocasión veremos cómo las interfaces tienen un papel muy importante cuando queremos usar ensamblados de .NET desde aplicaciones COM, por ejemplo desde Visual Basic 6, en las que queremos mantener la compatibilidad binaria para no forzar a recompilar los ejecutables cuando añadimos nuevos elementos a ese ensamblado, pero eso, será en otra ocasión, cuando veamos el tema de la interoperabilidad. ¡Nos vemos! dnm.servidores.sql Luis Miguel Blanco Ordenación de datos en Reporting Services Uno de los aspectos principales en cualquier generador de informes radica en la capacidad de ordenar los datos visualizados al usuario del modo más versátil posible. Reporting Services es una herramienta que nos ayuda enormemente en nuestro trabajo como diseñadores de informes, gracias a la extensa oferta de elementos que nos ofrece para la creación de informes en general, y la aplicación de ordenamiento a los datos mostrados en particular. En este artículo, tal y como apunta su título, nos ceñiremos al modo en cómo podemos ordenar los datos mostrados por un informe, describiendo las técnicas que a nuestro alcance pone Reporting Services para la consecución de dicho fin. Por tal motivo, se asume que el lector conoce los aspectos elementales en el proceso de creación de un informe básico, a efectos de poder entrar directamente en la descripción de los procedimientos necesarios para ordenar un listado. Respecto a los informes de ejemplo que utilizaremos, todos se encontrarán situados dentro de un proyecto de informes de Visual Studio .NET, y tomarán como origen de datos la tabla Customers de la base de datos Northwind de SQL Server. Igualmente, todos visualizarán los datos en una región de datos de tipo tabla de Reporting Services. Estos ejemplos se encuentran disponibles para su descarga como material de apoyo en la dirección www.dotnetmania.com. Y ya, sin más dilación, comencemos nuestra andadura por el universo de los informes ordenados. Aplicando un orden simple Luis Miguel Blanco es redactor de dotNetManía. Es consultor en Alhambra-Eidos. Ha escrito varios libros y decenas de artículos sobre la plataforma .NET (lalibreriadigital.com) El modo más básico de ordenar los datos de un informe consiste en establecer el criterio de ordenación de forma fija en la región de datos utilizada para visualizar la información. Como ejemplo de este tipo de caso crearemos un informe con el nombre rptOrdenBasico; una vez creado su origen de datos y añadidos los campos a mostrar en la tabla del diseñador, daremos los siguientes pasos para crear un orden por el campo Country: En primer lugar, situados en la pestaña “Diseño” del informe seleccionaremos la región de datos tabla, y a continuación haremos clic derecho en el indicador de tabla, que es el recuadro situado en su esquina superior izquierda, como muestra la figura 1. Al aparecer el menú contextual elegiremos la Figura 1 opción “Propiedades”, que abrirá un cuadro de diálogo en el que nos situaremos en la pestaña “Ordenación”. En la columna “Expresión” seleccionaremos de la lista desplegable el campo Country, en la columna “Dirección” dejaremos el valor por defecto, Ascending, como vemos en la figura 2. Pulsaremos el botón “Aceptar” y pasaremos a la pestaña “Vista previa del informe” para ver el resultado en ejecución, comprobando que los registros se ordenan por el campo anteriormente establecido. Como habrá observado, podemos construir nuestro orden para el informe basado en varios campos; <<dotNetManía << Algunas consideraciones iniciales 35 << dnm.servidores.sql Figura 2 tan sólo hemos de ir agregándolos en la forma que acabamos de explicar, y establecer su prioridad utilizando los botones de flecha arriba/abajo suministrados a tal efecto en esta ventana. La figura 3 muestra este informe en ejecución con un orden basado en los campos Country y City. de informe. Gracias a un parámetro tendremos la capacidad de asignar el campo de ordenación al ejecutar el informe, evitando la rigidez que supone crear un orden en diseño que no podemos alterar, como ocurría en el caso anterior. Ilustraremos este escenario de trabajo creando un nuevo informe con el nombre rptOrdenParametro, en el que incluiremos un parámetro asociado al orden de su región de datos, que nos permita seleccionar qué campo queremos utilizar para ordenar. Crear un parámetro es una labor muy sencilla; una vez que nos situemos en la pestaña “Diseño del informe”, seleccionaremos la opción de menú “Informe” + “Parámetros del informe”, que abrirá el cuadro de diálogo para el mantenimiento de parámetros. Pulsando el botón “Agregar”, crearemos un parámetro con el nombre parCamposOrdenar, de tipo String, como muestra la figura 4. Al ejecutar este informe desde la pestaña “Vista previa” no se mostrarán inmediatamente los datos como sucedía en el pasado ejemplo, ya que el motor de Reporting Services no sabe a priori el campo por el que queremos ordenar. En esta ocasión aparecerá en la barra de herramientas del informe una caja de texto perteneciente al parámetro creado, en la que teclearemos el nombre del campo de orden y pulsaremos el botón “Ver informe” para ejecutar el listado, como vemos en la figura 6. Figura 6 Téngase en cuenta que utilizando esta técnica se distinguen mayúsculas y minúsculas, por lo que al escribir el nombre del campo en el parámetro debemos hacerlo exactamente igual que aparece en la base de datos, o se producirá un error. Empleando una consulta dinámica Figura 4 Figura 3 <<dotNetManía Establecimiento del orden en tiempo de ejecución 36 Puede ser puntualmente interesante establecer el orden de un informe de forma fija e inamovible en un campo, pero la práctica nos dice en la mayoría de las ocasiones que el mejor diseño en este sentido es aquel que permite al usuario realizar la selección de aquellos campos por los que necesita ordenar el listado. Para solventar este tipo de situaciones, Reporting Services pone a nuestra disposición los denominados parámetros Tras asignar los valores de configuración necesarios en este cuadro de diálogo y pulsar el botón “Aceptar”, el parámetro será creado, por lo que nuestro siguiente paso consistirá en asociarlo con la expresión de orden del informe. Para ello, abriremos la ventana de propiedades de la tabla, y en la pestaña “Ordenación” escribiremos la expresión de forma que la colección Fields del informe utilice el parámetro en lugar de un campo fijo, como puede ver en la figura 5. Figura 5 Nuestra siguiente forma de ordenación consiste en el uso de una consulta dinámica de Reporting Services; característica que nos permite modificar en tiempo de ejecución la consulta SQL incluida en el informe, encargada de extraer los datos a visualizar. Una consulta dinámica se destaca porque dispone de una parte variable que está representada por un parámetro al que, como ya hemos visto, podemos asignar valor en tiempo de ejecución, siendo lo que dota a este tipo de consultas de su verdadera potencia. Como ejemplo de este tipo de ordenación crearemos el informe rptOrdenConsultaDinamica , que inicialmente elaboraremos de igual modo que los ejemplos anteriores en lo que respecta a su conjunto de datos y diseño. Al crear el parámetro para este informe lo definiremos como una lis- << dnm.servidores.sql Figura 7 Seguidamente volveremos a la pestaña “Datos” del informe y cambiaremos la consulta SQL para convertirla a dinámica, lo cual conseguimos encerrando entre comillas la parte fija de la consulta, concatenándola a continuación al parámetro del informe. Como resultado obtenemos una expresión evaluable por el motor de informes. Ver el siguiente código fuente: ="SELECT * FROM CUSTOMERS ORDER BY " & Parameters!parCamposOrdenar.Value Es importante hacer notar en este punto, que para que una consulta dinámica se ejecute adecuadamente, debemos eliminar todos los retornos de carro que pudieran existir. En nuestro ejemplo no se da tal circunstancia, pero téngase en cuenta para el caso de consultas SQL con mucho código. Completados todos los pasos de creación de este informe, al ser ejecutado desde la vista previa nos ofrecerá el parámetro como una lista desplegable, de la que seleccionaremos el campo para ordenar los datos. Ver la figura 8. Figura 9 Figura 8 Cuando diseñemos un informe que vaya a necesitar una consulta dinámica, recuerde que es recomendable comenzar el diseño del modo habitual, utilizando una consulta normal que devuelva los campos que vayamos a visualizar. Una vez que hayamos depositado dichos campos en el diseñador del informe, volveremos a la pestaña “Datos” y convertiremos la consulta en dinámica. Si empezamos la creación del informe directamente con una consulta dinámica, no se generarán automáticamente los campos que necesitemos emplear en la zona de diseño, y tendremos que crearlos manualmente. Ataque directo al código RDL Todo el proceso de creación de un informe a través del diseñador tiene como resultado la producción de un archivo con la extensión .RDL (Report Language Definition), que como su propio nombre indica, consiste en un lenguaje de definición basado en XML, que se utiliza en Reporting Services para escribir el código de los informes. Cuando estamos situados en el diseñador de informes, podemos visualizar el código RDL del mismo, para ello seleccionaremos la opción de menú de Visual Studio .NET “Ver” + “Código”. Adicionalmente, si el informe tiene sus datos ordenados, existirá un nodo con el nombre “Sorting”, que incluirá el subnodo “SortBy”, el cual, a su vez, contendrá los subnodos “SortExpression” y “Direction”, que son los que definen respectivamente el campo y dirección de ordenación para el informe, como vemos en la figura 9. La generación de código RDL del informe es un aspecto del que no tenemos que preocuparnos, ya que es el diseñador de informes el que se encarga de esta tarea, sin embargo, vamos a plantear a continuación un escenario de trabajo un tanto particular. Supongamos que hemos creado un informe con el nombre rptOrdenExterno, ordenado de forma fija por el campo Country, lo que hace que no podemos cambiar su orden mediante parámetros; pero tenemos la necesidad puntual de cambiar dicha ordenación a otro campo distinto desde una aplicación externa que acceda al servidor de informes y haga esta operación. Para lograr este propósito tenemos que comunicarnos con el servicio Web del servidor de informes, y a través del mismo acceder a nuestro informe, para poder manipularlo por código. A continuación describimos los pasos requeridos para llevar esta operación a cabo. En primer lugar crearemos un nuevo proyecto de tipo aplicación Windows (o ASP.NET según se prefiera) con el nombre CambiarOrdenInforme, y seleccionaremos la opción de menú “Proyecto” + “Agregar referencia Web”, que mostrará el cuadro de diálogo para la búsqueda de servicios Web. Haciendo clic en el enlace “Servicios Web del equipo local”, se realizará un rastreo de los instalados en nuestra máquina, localizando el correspondiente al servidor de informes: Report Service, como vemos en la figura 10. Figura 10 <<dotNetManía ta de valores, en la que asignaremos una etiqueta identificativa y el nombre del campo de orden para cada elemento de la lista. La ventaja de crear el parámetro de esta forma radica en que facilitamos al usuario la selección del campo de orden, evitamos potenciales errores por una incorrecta escritura del nombre del campo, y sólo permitimos que la ordenación se haga por los campos que realmente nos interesa exponer. Adicionalmente, y para que al comenzar a ejecutar el informe, este no aparezca vacío, introduciremos también como valor predeterminado uno de los nombres de campo. Véase la figura 7. 37 <<dotNetManía << dnm.servidores.sql 38 Tras hacer clic sobre el nombre de este servicio Web pulsaremos el botón “Agregar referencia”, lo que establecerá el enlace entre nuestro proyecto y dicho servicio, para así poder manipular los informes publicados en el servidor de informes a través de los métodos proporcionados por este servicio. Ver la figura 11. Seguidamente añadiremos al formulario de la aplicación un Combo Box, que rellenaremos con los nombres de los campos so bre los que orFigura 11 denaremos, y un Button, que al ser pulsado, ejecutará el código encargado de modificar el orden de los datos del informe. Como paso final del proceso, en el evento Click del botón escribiremos el código del fuente 1, en el cual, tras insFigura 12 tanciar un objeto correspondiente al servicio Web e identificarnos como un usuario válido, obtendremos la definición del informe. Posteriormente, gracias a las clases del espacio de nombres System.Xml, cargaremos la definición del informe en un documento XML y obtendremos el valor del nodo que contiene la expresión de ordenación, modificándola por el campo que hemos seleccionado en el formulario. Finalmente, pasaremos el documento XML del informe a un stream en memoria, y éste a un array de bytes que grabaremos como nueva definición del informe. En el fuente 1 se muestran las acciones que acabamos de describir. Una vez modificado el orden del informe de esta manera, podemos abrir una ventana del navegador Web e introducir la dirección http://localhost/ReportServer?/InformesOrdenados/rptOrden Externo, para comprobar que efectivamente, los datos se ordenan ahora en base al nuevo campo elegido. Imports Imports Imports Imports Imports '.... Private Informe de conclusiones ' si hay problemas al actualizar ' se muestran con el array de objetos Warning If Not (aAvisos Is Nothing) Then For Each oAviso As Warning In aAvisos MessageBox.Show(oAviso.Message) Next Else MessageBox.Show("Establecido nuevo orden de datos en el informe") End If End Sub A lo largo de este artículo hemos introducido al lector en las capacidades de ordenación de datos básica y avanzada con Reporting Services, una de las muchas características de esta interesante herramienta de generación de informes. Esperamos que todo lo aquí comentado le sea de utilidad en la creación de sus propios listados. Dim Dim Dim Dim Dim Dim Dim Dim Dim CambiarOrdenInforme.localhost System.Xml System.Text System.Net System.IO Sub btnCambiarOrden_Click ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnCambiarOrden.Click oRS As ReportingService sInforme As String aBytDefInforme() As Byte sCodInforme As String oXMLInforme As XmlDocument oNodoOrden As XmlNode msInforme As MemoryStream aBytNuevoInforme() As Byte aAvisos() As Warning ' instanciar un objeto del servicio web ' del servidor de informes oRS = New ReportingService ' asignar credenciales de identificación oRS.Credentials = CredentialCache.DefaultCredentials ' informe a manipular incluyendo ruta sInforme = "/InformesOrdenados/rptOrdenExterno" ' obtener el contenido del informe en formato binario aBytDefInforme = oRS.GetReportDefinition(sInforme) ' convertir el contenido del informe a texto sCodInforme = Encoding.Default.GetString(aBytDefInforme) ' crear un documento xml y cargar dentro el texto del informe oXMLInforme = New XmlDocument oXMLInforme.LoadXml(sCodInforme) ' localizar el elemento que contiene el campo de orden ' y cambiarlo por el valor del ComboBox oNodoOrden = oXMLInforme.GetElementsByTagName("SortExpression")(0) oNodoOrden.InnerText = "=Fields!" & Me.cboCampos.Text & ".Value" ' pasar el informe a un stream msInforme = New MemoryStream oXMLInforme.Save(msInforme) ' posicionar el stream saltando ' los códigos de control msInforme.Position = 3 ' pasar el stream a un array de bytes aBytNuevoInforme = New Byte(msInforme.Length - 4) {} msInforme.Read(aBytNuevoInforme, 0, aBytNuevoInforme.Length) ' grabar el array de bytes que contiene ' el informe modificado en el servidor de informes aAvisos = oRS.SetReportDefinition(sInforme, aBytNuevoInforme) Fuente 1 dnm.servidores.sql Jorge Serrano Atención MySQL, aquí dotNet, ¿me recibe? MySQL es el gestor de bases de datos open source líder en la actualidad. Independientemente de la plataforma donde se esté ejecutando este, podemos conectarlo con nuestras aplicaciones .NET usando algunas de las API de comunicación entre MySQL y aplicaciones Microsoft .NET existentes. En este artículo describiremos de forma sencilla cómo realizar esta tarea con VB.NET y C#. Jorge Serrano es redactor de dotNetManía. Es Ingeniero Informático y MVP de VB y de .NET. Es Webmaster de PortalVB.com y autor de diferentes libros y artículos técnicos. Jorge está entre los mejores profesores y conferenciantes sobre la tecnología .NET de nuestro país. veces con situaciones curiosas a la hora de abordar un determinado proyecto. De todos es sabido la proliferación y moda por los entornos y productos open source. Menos extendido en el conocimiento de todos son las diferencias existentes entre los productos de pago y los productos gratuitos, y por ello, en muchas ocasiones, nuestras decisiones están enfocadas y orientadas únicamente en el coste de los productos sin atender a otras características no menos importantes. Pero no deseo tratar ese tema de debate en este artículo, tan sólo mentarlo para que quien lo considere oportuno, recapacite sobre ello. Lo que no es menos cierto también en todo esto, es que dependiendo del tipo de cliente o del tipo de desarrollo a llevar a cabo, algunas veces es mucho más rentable acudir a entornos o productos de tipo open source. Ni todo tiene por qué ser de pago, ni todo tiene por qué ser open source; la virtud, en este caso, está en el camino medio de ambos puntos distantes, y por supuesto, alcanzarla y saber cuándo y cómo usar estas tecnologías en el momento preciso, es una tarea compleja. En el mundo de las bases de datos, está claro que los productos estrella implantados en las grandes empresas de todo el mundo son Oracle y Microsoft SQL Server (por algo será), pero no es menos cierto, que según el volumen o tamaño de una empresa, a veces estos robustos entornos de gestión de bases de datos no son muy bien vistos debido a su elevado coste (otra vez sale el tema dinero a la palestra de la toma de decisiones). Aún así, Microsoft dispone también de un entorno de nombre MSDE 2000, que no es otra cosa que una versión reducida y gratuita de Microsoft SQL Server 2000. En el año 2005, aparecerá su sustituto, de nombre Microsoft SQL Server 2005 Express (futuro MSDE 2005 para entendernos aunque el nombre de MSDE se perderá para siempre). Pero una vez más y en numerosas ocasiones, se dejan ver los defensores de otros entornos o productos que no tengan el signo o marca Microsoft por detrás –como si la marca Microsoft diera alergia– y por eso entre algunos de ellos, tenemos MySQL, el gestor de bases de datos open source líder en ese tipo de distribuciones. Una alternativa sin duda, muy a tener en cuenta también. Conociendo MySQL Basado en los términos GNU (General Public License), este producto es distribuido por MySQL AB, empresa comercial creada por los fundadores de MySQL, como software open source. MySQL tiene un logotipo muy curioso que es un delfín y cuyo nombre corresponde con Sakila, nombre que fue seleccionado por los fundadores de MySQL AB entre una amplia variedad de nombres sugeridos en Internet por otros informáticos. MySQL es un sistema gestor de bases de datos relacional, que cumple los estándares SQL y entre cuyas características encontramos que es un producto multihilo, capaz de soportar múltiples usuarios concurrentes. Ha sido escrito en C y C++ y está disponible para un amplio rango de sistemas operativos diferentes. Adicionalmente a esto, desarrollos independientes atesoran el crecimiento de MySQL y proporcionan <<dotNetManía << En el mundo de la informática, nos encontramos muchas 39 << dnm.servidores.sql herramientas de muy diversa naturaleza que nos facilitarán las tareas de mantenimiento, gestión y administración de nuestras bases de datos. Respecto a su escalabilidad, debemos tomar como referencias, las dadas por los usuarios de MySQL. Así, encontramos datos que indican que MySQL puede soportar cerca de 50 millones de registros, 60.000 tablas ó 5.000 millones de filas. Sin embargo, no queda claro el funcionamiento del sistema en cuanto a rendimiento cuando se manejan grandes cantidades de datos, tablas o filas. Acerca de las plataformas donde se aloja MySQL, cabe destacar que usarla en otras plataformas que no sean Microsoft Windows es una elección muy generalista. Sin embargo, lo que sí está claro, es que tengamos donde tengamos alojado nuestro servidor MySQL, en muchas ocasiones podemos tener la necesidad de conectar una aplicación .NET con este motor de bases de datos, y esto es justamente lo que veremos en este artículo. [ Más información Se puede recabar más información en el sitio web oficial de MySQL: http://www.mysql.com ] <<dotNetManía Sé quien soy y adónde quiero ir, pero ¿cuál es el camino? 40 Está claro que siempre que queremos comunicar un origen con un destino, necesitaremos un canal que nos permita esa comunicación. Por supuesto que sabemos quienes somos, ¿una aplicación .NET ejecutándose en un sistema Windows por ejemplo?. También se adónde quiero ir, ¿a encontrarme con MySQL que está instalado en un sitio localizado? Pero lo que a lo mejor no tengo claro del todo, es qué ruta tomar o qué rutas o alternativas tengo para llegar a mi destino sano y salvo. Sin duda necesitaré un camino, un driver o API que comunique ese origen con ese destino. Por suerte, para llevar a cabo este cometido, existen en Internet diferentes fórmulas o caminos que nos permi- En este artículo utilizaremos estas tres API, observando como particularidad, que la API de colaboración MySQLDriverCS, es un driver escrito enteramente en C#. Se trata en este últiFigura 1. El driver apropiado, nos permitirá establecer mo caso, de una contribución en canal de comunicación entre MySQL y nuestras open source que puede ser conaplicaciones .NET sultada en la página Web indicada en la tabla anterior. tirán comunicar nuestras aplicaciones Para llevar a cabo nuestro propósi.NET con MySQL. A continuación to, descargaremos por lo tanto cada una veremos algunos de ellos, gratuitos, de de las API comentadas, y las instalarefácil acceso y uso. mos en nuestro sistema. De este modo, En mi caso y para usar MySQL en mis tendremos nuestro sistema preparado, aplicaciones .NET, he usado la versión para utilizar cualquiera de las API que MySQL 4.1.7. En el lado de .NET es hemos seleccionado como óptimas. independiente el tipo de aplicación o el lenguaje a utilizar. En mi caso he utilizado como lenguajes de desarrollo, tanto NOTA VB.NET como C#, y aplicaciones Windows como tipo de proyecto. Lo Existen otras API de pago y estrictamente importante en sí, es la API posiblemente gratuitas en Internet. o driver, el cuál establecerá la comunicaEn este artículo, me he ceñido únición entre nuestras aplicaciones y MySQL camente al uso de las API marcacomo veremos a continuación. das como a tener en consideración por MySQL.com. Advierta además, que las versiones de las API pueEstableciendo nuestra vía de den variar cuando las quiera descomunicación cargar, ya que la mayoría de ellas, Tenemos dos tipos de API de comucorresponden a proyectos en consnicación entre MySQL y aplicaciones tante evolución Microsoft .NET que podemos establecer como diferentes: las API gratuitas y las API de pago. Entre las gratuitas, me gustaría destacar las que detalla la página ofiUsando MySQL ODBC 3.5.1 cial de MySQL y en las cuales me he basado para escribir este artículo. Estas son dos API declaradas como oficiales, y una MySQL ODBC 3.5.1 utiliza ODBC tercera API declarada como API de colacomo medio de comunicación, por lo boración, cuya responsabilidad recae que si dispone de Microsoft Visual curiosamente sobre un desarrollador espaStudio .NET 2002, deberá instalar los ñol independiente. Estas API son las que drivers de ODBC .NET Data Provider se detallan a continuación: para poder acceder a MySQL adecuadamente o a cualquier otra API de comunicación entre MySQL y aplicaciones base de datos a través de Microsoft .NET ODBC. En el caso de que disponga de Microsoft API oficiales Visual Studio .NET 2003, Connector/ODBC - MySQL ODBC driver v.3.5.1 ODBC .NET Data Provider http://dev.mysql.com/downloads/connector/odbc/3.51.html viene incorporado con .NET. MySQL Connector/Net 1.0.1 http://dev.mysql.com/downloads/connector/net/1.0.html Una vez instalado ODBC .NET Data Provider API de colaboración y MySQL ODBC 3.5.1 en MySQLDriverCS v.3.0.16b nuestro sistema, estaremos http://sourceforge.net/projects/mysqldrivercs preparados para crear un [ ] << dnm.servidores.sql [ Más información ODBC .NET Data Provider lo encontrará en la dirección web de Microsoft: http://www.microsoft.com/ downloads/release.asp?ReleaseID=35715 ] nuevo origen de datos ODBC como se muestra en las figuras 2 y 3. Figura 2.Antes de conectar con MySQL a través de ODBC, deberemos crear un nuevo origen de datos con el driver MySQL instalado en nuestro sistema cambio que existe con la inmensa mayoría de proyectos restantes es despreciable. Lo importante es importar el espacio de nombres System.Data.Odbc para poder trabajar con ella. En el formulario Windows, hemos añadido un control DataGrid y un control Button. El código de nuestra aplicación de ejemplo para VB.NET y C# es el que se detalla en el fuente 1. Figura 4. Nuestra aplicación en ejecución conectándose a través de ODBC con MySQL Imports System.Data.Odbc [...] Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)_ Handles Button1.Click ' Declaramos las variables de Conexión Dim objConexion As OdbcConnection Dim objDataAdapter As OdbcDataAdapter Dim objDS As New DataSet ' Establecemos la conexión con el DSN declarado objConexion = New OdbcConnection("DSN=PruebaMySQL") ' Asignamos al adaptador la instrucción SQL junto a la conexión a utilizar objDataAdapter = New OdbcDataAdapter("SELECT Nombre, Apellidos FROM tabla", objConexion) ' Volcamos los datos a un DataSet objDataAdapter.Fill(objDS, "ConectMySQL") ' Volcamos su contenido al control DataGrid DataGrid1.DataSource = objDS.Tables("ConectMySQL") ' Cerramos la conexión porque no la vamos a utilizar más objConexion.Close() ' Expandimos el control DataGrid para mostrar sus datos DataGrid1.Expand(0) End Sub Fuente 1 (VB) Una vez que estemos ya listos para iniciar nuestra andadura hacia MySQL, iniciaremos un nuevo proyecto en Microsoft Visual Studio .NET. En mi caso y como ya he comentado anteriormente, todos los proyectos de este artículo, están basados en proyectos Windows, si bien, el Fuente 1 (C#) Nuestra aplicación en ejecución es la que se muestra en la figura 4. Usando MySQL Connector 1.0.1 Una vez instalado MySQL Connector 1.0.1, observamos que esta API contiene <<dotNetManía Figura 3. Indicaremos los parámetros de conexión con la base de datos para establecer el canal que usaremos para comunicarnos con MySQL. Con el botón “Test”, podremos probar si la conexión está correctamente configurada using System.Data.Odbc; [...] private void button1_Click(object sender, System.EventArgs e) { // Declaramos las variables de Conexión OdbcConnection objConexion; OdbcDataAdapter objDataAdapter; DataSet objDS = new DataSet(); // Establecemos la conexión con el DSN declarado objConexion = new OdbcConnection("DSN=PruebaMySQL"); // Asignamos al adaptador la instrucción SQL junto a la conexión a utilizar objDataAdapter = new OdbcDataAdapter("SELECT Nombre, Apellidos FROM tabla", objConexion); // Volcamos los datos a un DataSet objDataAdapter.Fill(objDS, "ConectMySQL"); // Volcamos su contenido al control DataGrid dataGrid1.DataSource = objDS.Tables["ConectMySQL"]; // Cerramos la conexión porque no la vamos a utilizar más objConexion.Close(); // Expandimos el control DataGrid para mostrar sus datos dataGrid1.Expand(0); } 41 << dnm.servidores.sql tres componentes preparados para acceder a fuentes de datos MySQL de forma directa, tal y como se muestra en la figura 5. Figura 5. Componentes MySQL Connector 1.0.1 en Visual Studio .NET Estos componentes, están preparados para ser utilizados en Microsoft .NET Framework 1.0 y Microsoft .NET Framework 1.1. De hecho, hay dos grupos de componentes que podremos utilizar en ambos entornos. Nosotros, sin embargo, accederemos a MySQL en este artículo, a través de código directamente, por lo que iremos a la carpeta “References” de nuestro entorno Microsoft Visual Studio .NET para añadir la referencia a MySQL Connector 1.0.1 como muestra la figura 6, teniendo en cuenta la versión de Microsoft .NET Framework que estamos utilizando. <<dotNetManía Figura 6.Añadiendo la referencia de MySQL Connector 1.0.1 en Visual Studio .NET 42 De esta manera, lo primero que haremos será importar el espacio de nombres MySql.Data.MySqlClient y escribiremos a continuación el siguiente código para nuestras aplicaciones. Este código quedaría, en este caso, como se indica en el fuente 2. El resultado de ejecutar estas líneas de código es el mismo que hemos visto en los ejemplos anteriores. El cambio reside en la manera en la que conectamos con MySQL. Imports MySql.Data.MySqlClient [...] Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button1.Click ' Declaramos las variables de Conexión Dim strConexion As String Dim objConexion As MySqlConnection Dim objDataAdapter As MySqlDataAdapter Dim objDS As New DataSet ' Establecemos la conexión con el DSN declarado strConexion = "Database=test;Data Source=localhost;User Id=root;Password=dotnetmania" objConexion = New MySqlConnection(strConexion) ' Asignamos al adaptador la instrucción SQL junto a la conexión a utilizar objDataAdapter = New MySqlDataAdapter("SELECT Nombre, Apellidos FROM tabla", objConexion) ' Volcamos los datos a un DataSet objDataAdapter.Fill(objDS, "ConectMySQL") ' Volcamos su contenido al control DataGrid DataGrid1.DataSource = objDS.Tables("ConectMySQL") ' Cerramos la conexión porque no la vamos a utilizar más objConexion.Close() ' Expandimos el control DataGrid para mostrar sus datos DataGrid1.Expand(0) End Sub Fuente 2 (VB) using MySql.Data.MySqlClient; [...] private void button1_Click(object sender, System.EventArgs e) { // Declaramos las variables de Conexión string strConexion; MySqlConnection objConexion; MySqlDataAdapter objDataAdapter; DataSet objDS = new DataSet(); // Establecemos la conexión con el DSN declarado strConexion = "Database=test;Data Source=localhost;User Id=root;Password=dotnetmania"; objConexion = new MySqlConnection(strConexion); // Asignamos al adaptador la instrucción SQL junto a la conexión a utilizar objDataAdapter = new MySqlDataAdapter("SELECT Nombre, Apellidos FROM tabla", objConexion); // Volcamos los datos a un DataSet objDataAdapter.Fill(objDS, "ConectMySQL"); // Volcamos su contenido al control DataGrid dataGrid1.DataSource = objDS.Tables["ConectMySQL"]; // Cerramos la conexión porque no la vamos a utilizar más objConexion.Close(); // Expandimos el control DataGrid para mostrar sus datos dataGrid1.Expand(0); } Fuente 2 (C#) Usando MySQL DriverCS 3.0.16b La instalación de MySQL DriverCS conlleva la sorpresa adicional, de que se trata de una API o driver escrito completamente en C#, y el cuál realiza las funciones de conexión entre nuestras aplicaciones .NET y MySQL. De la misma manera que hemos hecho en el caso anterior, añadiremos a nuestro entorno de desarrollo, una refe- rencia al componente MySQL DriverCS tal y como se muestra en la figura 7. Una vez hecho esto, estaremos entonces preparados para utilizar esta API o driver y conectar así nuestras aplicaciones a nuestras fuentes de datos MySQL. Lo primero que haremos será importar el espacio de nombres MySQLDriverCS para utilizar este driver en nuestra aplicación, y escribir el código de nuestra aplicación (ver fuente 3). riores. La manera en la que deseamos conectar es la que varía y la que debemos elegir nosotros mismos, según nuestras necesidades. Conclusiones Figura 7 El resultado de ejecutar estas líneas de código es, una vez más, el mismo que hemos visto en todos los ejemplos ante- Como podemos observar, las similitudes de conexión a fuentes de datos MySQL son bastante cosiderables entre unas API o drivers y otros, aunque eso sí, existen algunas diferencias léxicas a tener en cuenta. Imports MySQLDriverCS [...] Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' Declaramos las variables de Conexión Dim objConexion As MySQLConnection Dim objDataAdapter As MySQLDataAdapter Dim objDS As New DataSet ' Establecemos la conexión con el DSN declarado objConexion = New MySQLConnection( New MySQLConnectionString("localhost", "test", _ "root", "dotnetmania").AsString) ' Asignamos al adaptador la instrucción SQL junto a la conexión a utilizar objDataAdapter = New MySQLDataAdapter("SELECT Nombre, Apellidos FROM tabla", objConexion) ' Volcamos los datos a un DataSet objDataAdapter.Fill(objDS, "ConectMySQL") ' Volcamos su contenido al control DataGrid DataGrid1.DataSource = objDS.Tables("ConectMySQL") ' Cerramos la conexión porque no la vamos a utilizar más objConexion.Close() ' Expandimos el control DataGrid para mostrar sus datos DataGrid1.Expand(0) End Sub Fuente 3 (VB) using MySQLDriverCS; [...] private void button1_Click(object sender, System.EventArgs e) { // Declaramos las variables de Conexión MySQLConnection objConexion; MySQLDataAdapter objDataAdapter; DataSet objDS = new DataSet(); // Establecemos la conexión con el DSN declarado objConexion = new MySQLConnection(new MySQLConnectionString("localhost", "test", "root", "dotnetmania").AsString); // Asignamos al adaptador la instrucción SQL junto a la conexión a utilizar objDataAdapter = new MySQLDataAdapter("SELECT Nombre, Apellidos FROM tabla", objConexion); // Volcamos los datos a un DataSet objDataAdapter.Fill(objDS, "ConectMySQL"); // Volcamos su contenido al control DataGrid dataGrid1.DataSource = objDS.Tables["ConectMySQL"]; // Cerramos la conexión porque no la vamos a utilizar más objConexion.Close(); // Expandimos el control DataGrid para mostrar sus datos dataGrid1.Expand(0); } Fuente 3 (C#) MySQL ODBC driver v.3.5.1 nos obliga a establecer una conexión ODBC y a usar System.Data.Odbc. Además, esta forma de conexión hace previsible que exista una diferencia de rendimiento entre el acceso ODBC y otros métodos de acceso. El acceso a través de ODBC siempre ha estado criticado por la falta de rendimiento y más aún si se compara con un driver de acceso nativo al gestor de bases de datos, como podría ser por ejemplo System.Data.SqlClient para Microsoft SQL Server 7.0 ó superior. MySQL Connector 1.0.1 es quizás el que más parecido tenga con System. Data.Odbc y el resto de espacios de nombres que permiten accesos a diferentes fuentes de datos. Su uso es bastante intuitivo y sencillo. Los componentes, nos facilitan asimismo, la posibilidad de escribir aplicaciones n-tier de forma rápida y sencilla. MySQL DriverCS es quizás a la hora de establecer la conexión con MySQL el driver más curioso. La forma en la que establece la conexión no es a la que nos tienen acostumbrados otros drivers, pero es igual de efectiva. No es tan completo como lo podría ser MySQL Connector 1.0.1 pero su simplicidad es a veces mucho más interesante que las características que nos pueda aportar otra API de conexión. Nótese además, que en nuestros ejemplos, hemos utilizado la instalación que MySQL realiza por defecto, por lo que el puerto de MySQL para establecer la comunicación es el puerto por defecto, el 3306. Si por razones que considerara oportunas, deseara modificar ese puerto a la hora de instalar MySQL, debe tener en cuenta que quizás deba hacer referencia al puerto directamente como parámetro de conexión, como puede ser el caso de la creación del origen de datos a través de ODBC o en el uso de MySQL DriverCS como parámetro del método MySQLConnection String. Aún así, hemos podido ver con ejemplos prácticos, cómo establecer comunicaciones con nuestras aplicaciones .NET y MySQL, utilizando para ello, diferentes API o drivers que nos han permitido establecer de una manera muy sencilla la comunicación efectiva con MySQL. <<dotNetManía << dnm.servidores.sql 43 dnm.arquitectura Daniel Mazzini ¡Mi madre es un Singleton! Siguiendo con el tema del último artículo, volvemos a tratar algunos patrones de diseño básicos. En este caso veremos el singleton. Si bien puede tener dos lugares distintos de donde se llaman, siempre es la misma instancia que atiende a la petición cliente. << Resumen Se asegura que solo se crea una instancia de una clase. Todos los objetos que usen una instancia de esta clase siempre usarán la misma instancia. Objetivo En principio se desea que se pueda acceder en una manera centralizada a un recurso único en el sistema. También puede usarse en los casos donde la creación de un objeto implique consumir demasiados recursos. De esta manera se crearía el objeto y quedaría guardado. Contexto de uso Es uno de los patrones que más utilizo cuando trabajo. Lo utilizo para centralizar la información como puede ser la información de conexión a un servicio Web, o de rendimiento, como puede ser crear la capa de datos solo una vez. Implementación: ¿Cómo se hace un Singleton? Daniel Mazzini colabora habitualmente con dotNetManía. Es Arquitecto de Sistemas de Información en Insert Sistemas. Imparte cursos tanto de C# como de Visual Basic.NET para Aula DAT y colabora en los talleres MSDN de Microsoft Ibérica. Lo primero que hay que tener claro es que nadie desde fuera de la clase puede crear una instancia, por tal motivo el constructor debe ser privado. Para poder obtener la instancia, necesitaremos de un método o propiedad. Este método no puede ser de instancia, sino de clase, es decir un static (o shared en Visual Basic) que siempre devuelve la misma instancia. La instancia que retorna es privada y static. El resto de lo que contenga la clase depende de la lógica de negocio que maneje. En el diagrama UML 1 se puede ver como queda. Diagrama UML 1 Una de las primeras preguntas que se me ocurrió cuando vi este patrón por primera vez fue “¿y por qué no usar todos los métodos estáticos?”. De hecho, la plataforma .NET tiene clases con todos métodos estáticos, como System.Console. Algunas de las razones puede ser que se debe usar una interfaz. Por ejemplo, si se crea una clase para reproducir audio y otra clase para reproducir vídeos, los dos deberían ser Singleton para no reproducir dos temas al mismo tiempo, y tener una interfaz IMovimientos, con métodos para adelantar o atrasar un tema. En el diagrama UML 2 se visualiza el resultado. Diagrama UML 2 << dnm.arquitectura Evitando copias Ya hemos visto que la idea de un Singleton es que sea una instancia única. Para mantenerla así, existen temas a tener presentes: • Serialización. Un objeto se serializa por distintas razones; generalmente porque es un objeto que se transfiere entre capas y debe pasar como binario o XML a otra capa, o simplemente para persistir su información en un archivo de disco. Un objeto Singleton no debe incluirse en ningún proceso de serializacion. • Clonación. El segundo tema a tener presente es la clonación. Un objeto Singleton no debe implementar la interfase IClonable, ni directa ni indirectamente. • Herencia. En cuanto a herencia, para que nadie pueda heredar de esta clase y crear más de una subclase, lo que generaría, en tiempo de ejecución, más de una instancia, se le indica a la clase del Singleton que no podrá ser heredada (sealed). • Sincronización de threads. El último tema, la sincronización de threads, es el más difícil de controlar a primera vista. El método que crea el Singleton es estático, es decir, que distintos thread podrían llamarlo, pudiendo pasar de tener 0 instancias a tener 2 instancias si dos thread entran por vez primera a crear la instancia. Para mitigar este problema usamos una técnica de programación de múltiples hilos llamado doble check, donde se chequea dos veces un valor, antes y después del bloqueo del thread. Evitando confusiones Algo que suele suceder con bastante frecuencia es que cuando desarrollamos una aplicación tenemos un objeto que es único para toda la aplicación, y queremos poder compartirlo desde distintas aplicaciones. En este caso, el Singleton que usaremos es el de remoting. Remoting me permite crear un objeto que vive en el servidor y que es el mismo para distintos clientes porque se comparte por referencia. El patrón Singleton me permite crear algo único para el mismo cliente de formulario Windows, como puede ser la información referente al menú y sus opciones visibles según los roles que tenga en la aplicación. Con aplicaciones Web la cosa cambia un poco porque tengo el objeto Application, colocando un objeto ahí será el mismo para todos los que accedan a la Web. Ventajas de este patrón • Existe solo una instancia de la clase. • Acceso de forma controlada a la instancia. No usamos variables globales. • Otras clases que hagan uso de la clase Singleton obtendrán una instancia por medio de un método estático, antes que construyéndolo. • El método que me trae la instancia encapsula el proceso de creación; a veces el proceso de creación puede significar realizar otra tarea, por ejemplo, abrir un archivo que hará de log. Podemos valernos de los archivos de configuración. Desventajas • Subclases. Debido a que el método estático es la clave para llegar a la instancia que está dentro de la clase Singleton, y como los métodos estáticos no pueden ser virtuales, y por ende sobrescribirse, esto genera problemas a la hora de crear una clase que herede del Singleton. Tendríamos que ocultar con el comando new. Roles El Singleton es un patrón muy sencillo en cuanto a roles porque solo consta de una clase. Singleton: Clase de de la cual queremos tener una única instancia. Ejemplo Podemos seleccionar en tiempo de ejecución a qué destino enviar un mensaje, a una cola de mensaje de MSMQ o a una colección cola. Para esto podemos hacer una interfaz llamada IMensajeria, que tenga dos métodos: uno para enviar mensajes y otro para cerrar la cola. El fuente 1 muestra el código de la interfaz. public interface IMensajeria { void Send(EntidadBase body); void Close(); } Fuente 1 <<dotNetManía Quizás la razón más importante para usar un Singleton antes que los métodos estáticos son los cambios; es posible, agregando no más de 10 líneas de código, hacer que una clase normal pase a ser Singleton, mientras que de la otra forma, tendría que pasar todo a estáticos, con el importante cambio que significa en la clase cliente. Por lo tanto, me da la posibilidad de pensar mi arquitectura sin interesarme la cantidad de instancias necesarias, luego agregaré las líneas necesarias si es de una sola instancia. En la sección de ejemplo se ven las líneas de código necesarias para crear el Singleton, todas ellas encerradas en una región. 47 << dnm.arquitectura ...se desea que se pueda acceder de una manera centralizada a un recurso único en el sistema.También puede usarse en los casos donde la creación de un objeto implique consumir demasiados recursos. De esta manera se crearía el objeto y quedaría guardado. Una vez creada la cola, debemos enviar el mensaje. Deseamos no tener que crear la cola cada vez, sino solamente enviar el mensaje. Para esto usaremos el patrón Singleton. El diagrama UML 3 muestra la estructura final. También estoy asociando lo explicado en el artículo anterior, un modelo SuperClase Abstracta. La razón es que me interesa enviar cualquier objeto siempre y cuando herede de EntidadBase. Todo esto se ejecuta desde una aplicación Windows, donde puede seleccionar si lo envió a una cola normal o a MSMQ. También puedo enviar un objeto u otro. Diagrama UML 3 Para facilitar la escritura desde el código cliente, he cambiado el método ObtenerInstancia por la propiedad Instancia de solo lectura. También se puede ver la creación retardada de la instancia, es decir, que hasta que no la necesita no se crea, así como el constructor privado. El fuente 2 muestra los pasos para crear la instancia única. private static Cola instanciaUnica; private static object lockObject= new object(); Queue queue; <<dotNetManía private Cola(){ queue= Queue.Synchronized( new Queue()); } 48 Figura 1 public static Cola Instancia{ get{ //doble check: //Es posible que un segundo thread este creando la //instancia mi entras se bloquea al primer thread //Por tal motivo, se vuelve a preguntar despues //del bloque si es null if (instanciaUnica==null) { lock(lockObject) { if (instanciaUnica==null) instanciaUnica= new Cola(); } } return instanciaUnica; } } Fuente 2 Patrones asociados Este sigue siendo un patrón básico, por lo tanto, encontramos muchos otros patrones: • Factory method: Generalmente las factorías de objetos son Singleton. Con una sola factoría alcanza. • Builder: Separa la construcción de un objeto de su representación, de forma que el mismo proceso pueda crear diferentes representaciones. La manera más fácil de entenderlo es la serializacion, donde tenemos un conjunto de caracteres con un determinado formato (XML, binario, SOAP) y a partir de aquí vuelve a crear distintos objetos. << dnm.mvp.online Jorge Serrano Campus MVP mayor vicio es la tecnología son algunas de las características de este grupo de personas afín a productos Microsoft. Lo que está claro, es que si usted está leyendo este artículo es porque tiene cierto interés sobre Microsoft .NET y la tecnología en general, su divulgación, expansión, aprendizaje, etc. En resumen, todo lo que sea aprender le llama la atención. El artículo de la sección dnm.mvp.online de este mes nos acerca a la iniciativa emprendida por Krasis (http://www.krasis.com), empresa especializada en las tecnologías de la información, y en la persona de José Manuel Alarcón, MVP de ASP/ASP.NET, que en su afán por divulgar la tecnología nos facilita enormemente la formación en línea a distancia sobre las tecnologías Microsoft en general y sobre .NET en particular. Todo en nuestro idioma. CampusMVP, la formación al poder Para hablar de esta interesante iniciativa, hay que hablar de campus , y para hablar de campusMVP en profundidad hay que explicar primero lo que es. campusMVP es una iniciativa promovida por Krasis y José Manuel Alarcón, y realizada con la colaboración de otros MVP en la que se ofrecen cursos de formación en línea sobre tecnologías Microsoft (tanto de programación como de sistemas) y en los que los contenidos y la tutorización es realizada exclusivamente por MVP. Este es su gran valor diferencial. No se trata de cursos pensados para obtener una certificación o título, sino que se dirigen a personas con la intención de progresar en sus conocimientos y en definitiva, hacer formación continua para ser cada vez mejores profesionales. Por eso son cursos cortos, de temas muy concretos y normalmente especializados, con un precio muy asequible tanto a nivel personal como empresarial. Aún así, las miras de campusMVP son mucho más amplias; entre otras cosas, permite incluso licenciar contenidos a empresas de formación que quieran comercializarlos por su propia cuenta. MVP Jorge Serrano es redactor de dotNetManía. Es Ingeniero Informático y MVP de VB y de .NET. Es Webmaster de PortalVB.com y autor de diferentes libros y artículos técnicos. Jorge está entre los mejores profesores y conferenciantes sobre la tecnología .NET de nuestro país. Algunas cosas sobre CampusMVP El hecho de que campusMVP haya apostado por la formación en línea a distancia no es casual. José Manuel, consciente de los ritmos de trabajo y desa- rrollo profesional, y las dificultades que hoy existen para acudir a lugares donde se pueda recibir formación sobre un producto en concreto (en muchas ocasiones la propia empresa prefiere contratar al formador para que vaya a su empresa a dar la formación), ha decidido este medio de formación debido a que esto permite al alumno elegir el horario más satisfactorio para él, y marcar así su propio ritmo de aprendizaje. Adicionalmente, la importante figura del tutor añadida a los cursos, respalda los conocimientos adquiridos y resuelve cualquier contratiempo o duda planteada en un momento en particular. Obviamente, si hablamos de formación en línea, hablamos de Internet y por ello, es razonable que el usuario disponga de una conexión a Internet a través de la cuál, poder llevar a cabo su aprendizaje. Todos los cursos están divididos en lecciones, y cada una de las lecciones en epígrafes. Los epígrafes son de pequeña duración, por lo que la flexibilidad a la hora de parar o continuar en un momento dado de la formación en línea es muy grande. El sistema informático implantado en la formación en línea, le permite siempre elegir qué quiere hacer cada vez que se sienta delante del PC. Puede retomar la formación en el lugar en el que lo dejó la última vez o puede ir a la parte del curso que desee. Otra de las características a reseñar de los cursos en línea de campusMVP es la información indirecta de apoyo de que dispone el alumno. De esta manera, los cursos se complementan con trucos, enlaces, preguntas frecuentes, etc. ¿Y los tutores? Los tutores son conocidos MVP con una larga experiencia en formación, escribiendo libros y artículos y preparando material técnico. A la hora de escribir este artículo, los MVP que participan como tutores de alguno de los cursos impartidos en campusMVP son: •José Manuel Alarcón (MVP ASP/ASP.NET) •Alejandro Mezcua (MVP Compact .NET Framework) •Alex A. Solano (MVP ASP/ASP.NET) •Guillermo Som “El Guille” (MVP Visual Basic) •Iván González (MVP Windows Server) •Jesús López “SQL Ranger” (MVP SQL Server) •Rodrigo Corral (MVP C++) <<dotNetManía << Que el objetivo principal de los MVP es compartir y que su 49 << dnm.mvp.online Los tutores no sólo preparan el material y contenido de los cursos, sino que además, colaboran con el alumno en las dudas o problemas que pueda encontrar en su aprendizaje. Se puede incluso enviar un mensaje de correo electrónico sobre una duda o problema puntual al tutor, o quedar con él en un chat a una hora determinada. ¿Qué cursos hay actualmente? • • • • • • • • campusMVP está en continuo crecimiento. Actualmente hay 8 cursos, aunque la idea y objetivo principal es ampliar ese número de cursos en el futuro. Los cursos actuales son los siguientes: C# para programadores de Visual Basic 6. Desarrollo de aplicaciones Web ASP.NET para dispositivos móviles. Fundamentos de desarrollo de aplicaciones Web con ASP.NET. Planificación, implementación y mantenimiento de Directorio Activo en Windows 2003. Programación asíncrona avanzada en la plataforma .NET. Programación de aplicaciones distribuidas con .NET Remoting. Seguridad avanzada de Internet Information Server. Técnicas de escritura de código seguro. Los costes de los cursos Los costes de los cursos son siempre un tema importantísimo. Hemos indicado ya que los cursos resultan bastante económicos. Dependiendo del curso seleccionado el coste suele rondar entre los 65€ y los 130€. La duración de los cursos también varía según el curso seleccionado. Si está interesado en conocer más a fondo esta forma de aprendizaje pero no se termina de decidir, debe saber que existe un curso gratuito y que le puede ayudar a familiarizarse con este innovador medio de formación en línea a distancia. El curso de Seguridad avanzada de Internet Information Server, le permitirá no sólo aprender conceptos sobre la seguridad de IIS sino que además podrá conocer de primera mano cómo funciona campusMVP. Más fácil no se nos puede poner ¿verdad? <<dotNetManía ¿Dónde está CampusMVP? 50 campusMVP es una iniciativa virtual, por lo que deberemos acudir a la página Web http://www.campusmvp.com para poder acceder a todo el material referente a los cursos. Allí encontraremos todo lo que necesitamos, precios, duraciones, cursos que se pueden recibir, descripción de los cursos, preguntas y respuestas frecuentes, precios especiales a empresas, etc. Para cualquier duda respecto a los cursos, se recomienda visitar la página Web de campusMVP, donde podrá plantear sus dudas o preguntas. Sobre Jose Manuel Alarcón José Manuel Alarcón es MVP de Visual Developer ASP/ASP.NET desde abril de 2004. Ingeniero superior industrial especializado en diseño de máquinas, posee el título de Especialista Universitario en Consultoría de Empresa. Estos antecedentes no lo conducían precisamente al mundo de la informática, José Manuel Alarcón hasta que un soleado día de mayo de hace ya muchos años (demasiados) se contagió del “vicio del sicilio”, como él lo llama. Comenzó programando calculadoras HP-48 en lenguaje RPL para resolver problemas técnicos, pero enseguida se introdujo en el mundo de la informática profesional desarrollando también aplicaciones de ingeniería. Su primer gran proyecto “serio” fue un entorno de simulación de ciclos termodinámicos aunque realizó algunos desarrollos más relacionados con la ingeniería. Eso fue antes de dejarla definitivamente de lado para dedicarse a la informática de modo profesional. Desde entonces ha visto publicados varios libros de programación e ingeniería, y es colaborador en diversas publicaciones del sector TIC, como dotNetManía, PC World, Windows TI Magazine, etc., siendo autor de cerca de 300 artículos. Colabora con Microsoft en la impartición de seminarios y en su revista empresarial (www.empresas.microsoft.com). En la actualidad es socio de Grupo Femxa, un grupo empresarial gallego de servicios profesionales donde dirige diversos proyectos tecnológicos centrados en la teleformación y los servicios a ISP fundamentalmente. Puedes encontrarlo en su blog sobre programación .NET en www.jasoft.org. Desde aquí mandamos un cordial y afectuoso abrazo a José y nuestros mejores deseos para su pronta recuperación después del percance que sufrió cuando se estaba elaborando este artículo. Por suerte para todos y sobre todo para el bueno de José y quienes le rodean, todo quedará en una mera anécdota. Si quieres saber más sobre el programa MVP puedes consultar la página de Microsoft en: http://mvp.support.microsoft.com Conclusión Como vemos, Internet nos proporciona todas las herramientas para aprender y formarnos a distancia. Sólo hace falta tener cursos y contenidos de calidad y campusMVP los proporciona. Las empesas de hoy en día son muy reticentes a la formación; en los costes de formación no sólo se deben tener en cuenta el propio coste del paquete de formación en particular, sino los costes derivados en traslados, horarios, dietas, etc. Los métodos de formación como los que nos presenta campusMVP, permite a la empresa tener una flexibilidad mucho mayor y acondicionar el ritmo de formación al ritmo de trabajo y desarrollo profesional del trabajador. De esta manera, es posible sacar un mayor provecho de a la formación y al trabajador. dnm.todotnet.qa Dino Esposito ASP.NET 2.0 está aterrizando Dino Esposito es redactor de dotNetManía. Formador, consultor y escritor afincado en Roma. Miembro del equipo de Wintellect, Dino está especializado en ASP.NET y ADO.NET. Puede enviarle sus consultas a [email protected] otra el control DataGrid. Y no me refiero a controles de terceros, sino al DataGrid que viene con el producto de forma nativa. En ASP.NET 2.0, este control está totalmente soportado (no podía ser de otra forma), pero parece que su hermano mayor, el control GridView, va a sustituirlo en muchas situaciones comunes. Aparte de unos pocos miembros cambiados de nombre y un modelo de objetos ligeramente diferente, ambos controles se parecen mucho. Sí que es cierto, que GridView dispone de un modelo de objetos más claro y refinado y unos cuantos miembros adicionales, aparte de incorporar el feedback de dos años de experiencia real. Pero a primera vista, ambos parecen iguales, y muchos desarrolladores se preguntan si son necesarios los dos. No hay duda de que DataGrid debe estar en ASP.NET 2.0 para garantizar la compatibilidad hacia atrás y migración suave de aplicaciones. Así que la pregunta real es ¿por qué necesitaríamos un nuevo control GridView? ¿Cuál es el nuevo valor real que ofrece? La primera pregunta de este mes tiene que ver con el DataGrid, pero la he seleccionado también por que puede ilustrar las diferencias respecto al nuevo control. Tengo una columna Identity en una tabla enlazada a un DataGrid. Quiero que los usuarios puedan seleccionar una fila y ejecutar ciertas acciones sobre la tabla vinculada con ella. ¿Cómo hago esto sin mostrar la columna Identity en el DataGrid? Si la columna fuera visible, podría encontrar su valor buscando el dato literal asociado. Pero no quiero que se muestre la columna. Ayuda, por favor. Bueno, esta es una pregunta típica de principiantes en el DataGrid. Pero, marca una diferencia significativa entre el DataGrid y el GridView. Veamos primero lo relativo al DataGrid. La solución propuesta es válida tanto para ASP.NET 1.x como para ASP.NET 2.0. Para mantener accesibles los valores de una columna Identity sin mostrarla, basta con añadir esa columna al DataSet vinculado al control. Para que no se vea, se la mantiene fuera de las columnas enlazadas al DataGrid. Al mismo tiempo, tienes que informar al DataGrid de la existencia de una columna cla- ve. Eso lo harás asignando a la propiedad DataKeyField el nombre de la columna Identity. Pongamos que la columna identidad se llama EmployeeID. En ese caso, sería: <asp:DataGrid … datakeyfield="employeeid" … /> Cuando se asigna DataKeyField, el DataGrid rellena la propiedad DataKeys (un array de objetos) con los valores de la columna especificada correspondientes a los registros mostrados. Este array contiene tantos elementos como filas se muestran en el DataGrid. Cada elemento contiene el valor del campo clave para el registro enlazado. En este punto, si conoces el índice de la fila seleccionada, (cuyo primer elemento es el 0), puedes ejecutar el siguiente código. Vamos a suponer que el campo clave es un entero: int key = (int) grid.DataKeys[rowIndex]; El índice de la fila seleccionada puede obtenerse de varias formas, dependiendo de la interfaz de usuario de la rejilla de datos. Si la rejilla tiene una columna Select, la propiedad SelectedIndex devuelve el índice de la fila. Si necesitas la clave de la fila en edición, la propiedad es EditIndex. Si quieres lanzar una acción personalizada (por ejemplo desde un botón “Columna”), se obtiene el índice de la fila seleccionada a partir del evento de la estructura de datos. Por ejemplo, el parámetro pasado al evento ItemCommand –de la clase DataGridCommandEventArgs– dispone de una propiedad Item.ItemIndex. En cualquier caso, es importante que el campo clave sea parte del origen de datos enlazado al DataGrid. Podría pensarse que el mismo modelo es aplicable igualmente al control GridView. Sin embargo, aunque el modelo no es radicalmente diferente, existen ciertas diferencias que merecen la pena considerarse. De acuerdo, ya me ha picado la curiosidad. Estoy deseando saber cuáles son las diferencias entre los dos controles. Imagina un escenario en el que tienes una columna Grid Button, para lanzar cualquier acción, por ejem- <<dotNetManía << Muchas aplicaciones ASP.NET emplean de una forma u 51 52 [email protected] <<dotNetManía [email protected] << dnm.laboratorio.net plo, añadir un elemento al carrito de la compra. Con los GridView el índice de la fila seleccionada no es transportado por la estructura de datos del evento (como en el DataGrid). Para buscarlo, tienes que recurrir a la propiedad CommadArgument. Sería de la siguiente forma: void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName.Equals("AddToCart")) { int rowIndex = Convert.ToInt32(e.CommandArgument); } } <asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" BackColor="white" DataKeyNames="productid,productname,unitprice" AutoGenerateColumns="false" AllowPaging="true" OnRowCommand="GridView1_RowCommand"> <Columns> <asp:boundfield datafield="productname" headertext="Product" /> <asp:boundfield datafield="quantityperunit" headertext="Packaging"/> <asp:boundfield datafield="unitprice" headertext="Price" DataFormatString="{0:c}" /> <asp:buttonfield buttontype="Button" text="Add" CommandName="Add" /> </Columns> </asp:GridView> Fuente 2 Fuente 1 Hay que notar que el evento ItemCommand del DataGrid es reemplazado por RowCommand en un GridView. Cierto código de ejemplo en la documentación de la Beta 2, sugiere que el usuario debería de poner el índice en el CommandArgument manualmente escribiendo su propio manejador para el evento RowCreated. Pero otro código fuente de ejemplo en la misma documentación utiliza el código indicado antes, y funciona perfectamente. Así que vamos a asumir un bug comprensible y temporal en la documentación. El código muestra cómo obtener el índice de la fila seleccionada. El evento RowCommand se produce para cada botón pulsado de cada fila del grid. Si dispones de múltiples columnas de botones, podrías necesitar asegurarte de que el evento que manejas es el adecuado. Para ello, puedes comprobar la propiedad CommandName. El siguiente problema a abordar, es cómo obtener los datos correspondientes a la fila seleccionada. Donde esos datos pueden ser de cualquier clase almacenada en el origen de datos. Si el grid está vinculado a un objeto DataTable, los datos correspondientes serán un objeto de tipo DataRow. Si el grid se enlaza a una colección personalizada, como por ejemplo una colección de Clientes, el ítem de datos se corresponderá con un cliente individual. Lo mejor que puedes hacer es aprovechar la colección DataKeys, que ha sido ampliada en esta versión para soportar múltiples campos y no solo un campo clave (con los DataGrid, el campo clave debe ser único, aunque la tabla subyacente no posea ningún campo de este tipo). Así que estableces uno o más campos clave para ser manejados por la colección DataKeys. Puedes considerar a la colección DataKeys como una colección de datos personalizados para ser recuperados de forma inmediata y sencilla. En el fuente 2 puede ver un GridView de ejemplo. Puedes usar la nueva propiedad DataKeyNames para establecer la lista de campos cuyos valores se almacenarán en la colección de DataKeys para acceso rápido. La propiedad DataKeyNames es la contrapartida de la propiedad DataKeyField en los DataGrid. Es un array de strings en lugar de una cadena simple. Los valores de todos los campos en la propidad DataKeyNames se empaquetan en un elemento de la colección DataKeys. La forma de obtener los valores asociados es la siguiente: void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName.Equals("AddToCart")) { // Get the index of the clicked row int rowIndex = Convert.ToInt32(e.CommandArgument); // Add the item to the shopping cart AddToShoppingCart(rowIndex); } } private void AddToShoppingCart(int rowIndex) { DataKey data = GridView1.DataKeys[rowIndex]; ShoppingItem item = new ShoppingItem(); item.NumberOfItems = 1; item.ProductID = (int) data.Values["productid"]; item.ProductName = data.Values["productname"].ToString(); item.UnitPrice = (decimal) data.Values["unitprice"]; MyShoppingCart.Add(item); ShoppingCartGrid.DataSource = MyShoppingCart; ShoppingCartGrid.DataBind(); } Fuente 3 Es esta página de ejemplo, ShoppingCartGrid es un grid de apoyo que utilizo para mostrar los elementos del carrito de la compra. Esta enlazado a una colección personalizada de tipos ShoppingCart poblada con objetos ShoppingItem. La colección personalizada del carrito se almacena en el objeto Session, y se recupera a través de la propiedad MyShoppingCart. A continuación se ilustra esto con un pseudo-código: << dnm.laboratorio.net tores de expresiones predeterminados, tal y como aparecen en la tabla adjunta: Syntax Description Y por último, DataKeys. Por diseño, devuelven un array de objetos DataKey, con tantos campos como elementos haya en la propiedad DataKeyNames del GridView. La forma de recuperar un campo concreto es la siguiente: AppSettings:XXX Devuelve el valor de la configuración especificada en la sección <appSettings> del fichero configuración ConnectionStrings:XXX Devuelve el valor de la cadena especificada en la sección <connectionStrings> del fichero de configuración. Resources:resourcefile, XXX Devuelve el valor del recurso global especificado en el fichero .RESX. item.ProductID = (int) data.Values["productid"]; En general, las propiedades contenidas en el nuevo GridView son una extensión y mejora de las existentes en el antiguo control DataGrid. Como consejo final, ten en cuenta que, cuantos más campos se almacenen en la colección DataKeys, más sobrecargado estará el campo ViewState. Como puedes suponer, los contenidos de DataKeys son almacenados en la propiedad ViewState de la página, para no tener que recuperarlos entre viajes al servidor. Soy relativamente nuevo en ASP.NET 2.0 y no acabo de comprender exactamente cuál es el significado de esos símbolos $ que he visto en código fuente de ejemplos. En concreto, parece que está relacionado con las cadenas de conexión y los controles DataSource. ¿Puede explicárnoslo? Por suerte, el símbolo $ no significa costes ocultos de ninguna clase; ni tampoco que haya que pagar ninguna clase de “royalties” por página. Es solamente el identificador de un nuevo tipo de expresiones en tiempo de ejecución. En ASP.NET 2.0 existen 3 tipos de expresiones, de las cuales, las dos primeras estaban soportadas por ASP.NET 1.x: 1) Bloques clásicos de ASP: <% … %> y <%= … %> 2) Enlaces a datos de ASP.NET 1.x <%# … %> 3) Nuevos enlaces a datos ASP.NET 2.0 <%$ … %> No son sinónimos, así que explicaremos las diferencias. Los primeros existen por compatibilidad con ASP clásico. La línea de código interna se integra con la página y se ejecuta cuando ésta es interpretada. Las expresiones con el prefijo # son expresiones de enlaces que solo son interpretadas después de una llamada al método DataBind(). En realidad, no son expresiones dinámicas, ya que son evaluadas solo dentro del contexto de la propia llamada de enlace. ASP.NET 2.0 suministra una infraestructura hecha a medida para expresiones dinámicas, basadas en un nuevo juego de componentes, los constructores de expresiones (Expression Builders). Las expresiones dinámicas tienen una sintaxis similar a la del DataBinding, excepto que utilizan el prefijo $ en lugar de la almohadilla (#). Las expresiones dinámicas se evalúan cuando se compila la página. El contenido de la expresión es extraído, transformado en código, e insertado en el código asociado con la página. Existen unos construc- Para enlazar una propiedad de un control al valor de una expresión de forma declarativa se sigue el esquema <%$ expresión %>. La sintaxis exacta es definida por el constructor asociado a cada tipo de expresión. Sólo se pueden usar expresiones dinámicas para asignar un valor a una propiedad de un control. No puedes incrustar el valor devuelto en el cuerpo de una página. DotNetNuke ha estado haciendo mucho ruido últimamente y existen un par de libros publicados sobre el tema. Nuestra compañía lo ha estado revisando como una posible plataforma para una consola de administración basada en Web. Con la venidera versión de ASP.NET 2.0 Portal Framework, parece que muchas de las características que poseía se encuentran en esta versión. ¿Crees que DotNetNuke desaparecerá cuando salga la nueva versión de ASP.NET 2.0? Creo que DotNetNuke es una forma sencilla, o –mejor aún– asequible, de construcción de aplicaciones Web ASP.NET para muchos desarrolladores que no conocen suficientemente la plataforma, o no tienen tiempo de hacerlo. DotNetNuke suministra un modo rápido de construir sitios Web de ciertos tipos. El ASP.NET Portal Framework (o sea, ASP.NET 2.0 Web Parts) es una forma de construir fácilmente ciertos tipo de páginas Web. Más en general, existen ciertas similitudes entre DotNetNuke y los kits de inicio de ASP.NET. Sin embargo, los kits de inicio, se enfocan más bien a aplicaciones verticales, mientras que la plataforma DotNetNuke es de tipo horizontal. Una consola de administración es un tipo de aplicación Web relativamente simple, con pocas páginas y un diseño sencillo. ¿Podría hacerse con DotNetNuke? Por lo poco que conozco de la herramienta, creo que sí. ¿Es la mejor opción? Eso es difícil de decir. Necesitarías un alojamiento Web que lo soporte específicamente, y algunos conocimientos concretos. Probablemente no muchos, y nada que un buen equipo de desarrollo no pueda abordar, pero para el caso que propones, un tipo de aplicación así, podría ser enfocado más fácilmente mediante los mecanismos tradicionales. DotNetNuke es estupendo si tienes que construir muchos sitios Web en muy poco tiempo, o si el equipo de desarrollo no tiene experiencia en aplicaciones Web. Por último, el producto estará disponible con toda seguridad después de la aparición de la nueva versión de ASP.NET. Traducción por Marino Posadas <<dotNetManía public ShoppingCart MyShoppingCart { get {return Session["MyShoppingCart"];} set {Session["MyShoppingCart"] = value;} } 53 dnm.laboratorio.net Pedro Pozo Component Art Web UI 2.1 Cuando se analizan las características de las aplicaciones Web siempre se pone como desventaja de las mismas que tienen un interfaz más pobre que las aplicaciones Windows. Pues bien, gracias a Component Art podemos llegar a conseguir un interfaz de usuario para aplicaciones Web tan atractivo como el de una aplicación Windows. << Component Art Web UI 2.1 son un conjunto de componentes cuya utilidad principal es la mejora del interfaz de usuario en aplicaciones Web. Estos componentes permiten al desarrollador de aplicaciones Web mejorar las capacidades de navegación a través de las páginas Web, manteniendo la compatibilidad con los principales navegadores del mercado. Así, mediante estos componentes, tendremos características tan poco comunes en las aplicaciones Web como drag & drop, menús interactivos, scroll de contenidos, desplazamiento y alineación de controles, entre otros. Cabe destacar que aunque son componentes de pago, podemos utilizar una versión de prueba durante 30 días y que si finalmente nos decidimos por comprarlos además de la licencia de uso también nos proporcionan todo el código fuente de estos componentes, con las ventajas que esto supone. También incluye numerosos ejemplos de cómo utilizar cada uno de los componentes, que ofrecen mucha funcionalidad y son bastante sencillos de programar. La ultima versión de Component Art Web UI está formada por los siguientes componentes: Menu Pedro Pozo es redactor de dotNetManía. Es es consultor e-Bussines. Ingeniero Técnico Informático de Sistemas y Webmaster del portal para desarrolladores .NET Framework Clikear.com Este componente para crear menús se basa en XML y CSS, de forma que podemos personalizar los menús de nuestros desarrollos Web sin necesidad de volver a compilar. Tan solo modificando el XML que define nuestro menú podemos modificar el contenido y modificando la hoja de estilos CSS podremos modificar su aspecto. Pero, por supuesto, si queremos programar nuestro menú disponemos de eventos de servidor, para poder desarrollar las acciones que queremos que ejecute cada una de las opciones de nuestro menú. En cuanto a la personalización del menú, nos ofrece una gran variedad de posibilidades como menús Componente Menu contextuales, teclas de acceso rápido, inserción de iconos en las opciones de menú, submenús anidados y numerosas posibilidades de diseño. Además, los menús que generamos son compatibles, como el resto de componentes, con los principales navegadores como Internet Explorer, Netscape, Mozilla, Safari y Konqueror, entre otros. TreeView Este componente merece la pena que le dediquemos una especial atención, ya que ofrece unas posibilidades de interactuar con él que no suelen ser habituales en un componente para Web. Si bien se trata de un componente clásico que nos permite mostrar una lista de cosas en forma de árbol que se puede ir desplegando por nodos, las características de este componente lo hacen especialmente atractivo para crear un interfaz de usuario interactivo. Este TreeView nos permite por ejemplo arrastrar y soltar cualquiera de sus nodos para cambiarlo de localización dentro del árbol. También nos permite cambiar el nombre de cualquiera de sus nodos y todo esto sin tener que recurrir a recargar la página. Así como otras << dnm.laboratorio.net NavBar Con este componente podremos generar menús, al estilo de los menús desplegables que ofrece Outlook. Disponemos de varias opciones y cuando seleccionamos alguna de esas opciones se nos despliega una lista desplegable que puede ser un sencillo texto que puede ir acompañado con iconos y diseños más complejos. Cabe destacar que la creación del contenido de este comComponente NavBar ponente puede tener como origen una consulta a una base de datos, un fichero XML o una programación personalizada. TabStrip Se trata del típico control de pestañas que nos podemos encontrar en numerosas aplicaciones Windows para clasificar contenidos de un mismo formulario, pero para aplicaciones Web. Con este componente podremos personalizar hasta el último detalle de las pestañas, pudiendo incluir gráficos, modificar tamaños y colores, colocán- dolas en horizontal o vertical e incluso añadirles scroll. También nos proporcionan numerosos ejemplos que nos permitirán utilizar diseños ya prefabricados, y la posibilidad de incluir cualquier componente dentro del TabStrip para personalizarlos. MultiPage Este componente sirve para generar varias subpáginas que están incluidas en una única página, y que puden ser mostradas en cualquier momento activándolas desde la página que Componente MultiPage las contiene. Este componente es similar al control multipágina que ya pudimos ver en los IE WebControls. Cabe destacar que los controles de este componente pueden ser cargados y accedidos directamente desde la página Web sin necesidad de usar el método FindControl. SiteMap Este componente nos permite crear un mapa de nuestra Web basándose en XML. Los diseños que nos ofrece son muy variados a través de plantillas predefinidas, aunque también se puede crear un diseño personalizado con hojas de estilo CSS e iconos. Rotator Este componente nos permite crear una rotación de contenidos en una página Web sin necesidad de recargar la página, ni de plugins. Tan solo utilizando HTML, Javascript y ASP.NET podemos obtener unos efectos realmente interesantes en los que podemos ver rotar desde banners publicitarios hasta contenidos con texto. Muy útil cuando se quieren poner contenidos que van rotando de forma que aprovechamos un pequeño espacio de Componente Rotator nuestra Web para p o d e r mostrar varios contenidos que van cambiando en interva- los de tiempo predefinidos. Los diseños que nos permite crear son muy variados y todos ellos fácilmente configurables a través de las propiedades del componente. En cuanto a los contenidos se pueden cargar a través de un enlace a una base de datos, mediante un XML o mediante programación. Snap Este componente permite definir zonas donde poder posicionar nuestros controles, incluyendo las opciones de movimiento, arrastrar y soltar, alinearlos y cambiar su tamaño, entre otras. Conclusión Si queremos crear un interfaz de usuario profesional para nuestras aplicaciones Web que permita al usuario tener un entorno similar al de una aplicación Windows, Component Art Web UI nos ayudará en gran medida en esta labor. Estos componentes nos ofrecen la posibilidad de crear una capa de presentación completa, interactiva y amigable para el usuario y muy sencilla de crear y mantener para el programador. Quizá se echa en falta una versión light gratuita, pero en este caso la calidad de estos componentes justifica su precio. Ficha técnica Nombre Component Art Web UI Versión 2.1 Fabricante Component Art Web http://www.componentart.com Categoría Componentes Precio Valoración A partir de 499$ <<dotNetManía características como teclas de acceso rápido, posibilidad de utilizar plantillas, inclusión de iconos y diferentes efectos para expandir y cerrar los nodos. Componente TreeView La carga de datos del árbol es muy sencilla, pudiendo hacerlo a través de un enlace a una base de datos, a través de XML o simplemente programándolo a gusto del desarrollador. 55 Suscríbase y llévese el CD Volumen 1 GRATIS AG OT AD O AG OT AD O Aún está a tiempo ❑ Nº5 ❑ Nº6 ❑ Nº 7 ❑ Nº8 ❑ Nº9 ❑ Nº11 ❑ Nº12 ❑ Nº13 ❑ Nº14 ❑ Nº15 Nº16 ❑ Nº10 AG OT AD O Nº4 Nº17 Oferta válida sólo para España hasta el 30 de septiembre de 2005 o hasta agotar existencias ✃❑ ❑ Deseo suscribirme a dotNetManía por un año (11 números) por un precio de 60,00€ IVA incluido y recibir el CD Volumen 1 con los 11 primeros ejemplares en formato PDF de alta calidad de forma gratuita. Deseo que me envíen los números atrasados marcados por un precio de 6,00€ IVA incluido cada uno. DATOS DE ENVÍO CIF/NIF. . . . . . . . . . . . . . . . . . . . Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DATOS DE FACTURACIÓN (sólo si son distintos a los datos de envío) CIF/NIF. . . . . . . . . . . . . . . . . . . . Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Usted autoriza a la mecanización FORMA DE PAGO de estos datos. El responsable y ❑ Talón nominativo a nombre NETALIA, S.L. destinatario de éstos es Netalia, ❑ Transferencia bancaria a nombre de NETALIA, S.L. a: S.L. Usted tiene derecho a acceLa Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia) der a sus datos, modificarlos y ❑ Domiciliación Bancaria (con renovación automática, previo aviso) cancelarlos cuando lo desee. Sus Indique su número de cuenta: datos no serán cedidos en ningu❑ Tarjeta de crédito na de las formas posibles a terceras partes y no se utilizarán más ❑ VISA ❑ MASTERCARD que para el buen funcionamienNúmero de su tarjeta: to de su suscripción a la revista Fecha de caducidad: / (imprescindible) Firma y/o sello a de Puede enviar sus datos por Fax al 91 499 13 64, o por teléfono al 91 666 74 77, o por email a la dirección [email protected], o también puede enviarlos por correo postal a la siguiente dirección: de 20 dotNetManía y para informarle de las actividades comerciales que realice la editorial Netalia, S.L. Si no desea recibir información comercial de dotNetManía marque la casilla siguiente ❑ Netalia, S.L. C/ Robledal, 135 28529- Rivas Vaciamadrid (Madrid) << dnm.biblioteca.net dnm.biblioteca.net Visual Studio Hacks James Avery Editorial: O'Reilly ISBN: 0596008473 Páginas: 478 Publicado: Marzo, 2005 Idioma: Inglés Avery es colaborador habitual de MSDN Magazine y ASP Today, además de autor de varias obras para las editoriales Wrox y Microsoft Press. Hackers de sitios Web Joel Scambray y Mike Schema Editorial: McGraw-Hill ISBN: 8448133781 Páginas: 412 Publicado: Enero, 2003 Idioma: Castellano Aunque no es la temática habitual de desarrollo, no podemos por menos de recomendar esta obra, ahora que la seguridad está cobrando cada vez más importancia en la construcción de las aplicaciones. Scambray, que ya había colaborado anteriormente en varias obras del mismo estilo, analiza esta vez la problemática de la construcción de aplicaciones Web seguras, desde el punto de vista del hacker que las ataca. Cuenta con la colaboración del asesor para seguridad Mike Schema, especialista en soluciones seguras para grandes corporaciones en Foundstone Inc. La obra recorre muchos aspectos de seguridad práctica, tanto desde el punto de vista del servidor Web, como del cliente. Los mecanismos de autenticación, la autorización, ataques a la administración de estado de la sesión, validaciones, SQL-Injection, y muchos otros, concluyendo con el análisis de un par de casos reales y unas valiosas listas de comprobación de seguridad antes de la implantación. <<dotNetManía << Se trata de un libro sobre trucos y optimización de uso del IDE de Visual Studio. Aunque sólo su temática ya lo convierte en suficientemente interesante, es raro que cualquiera que utilice el IDE como herramienta habitual no encuentre un montón de cosas útiles, de esas que no miramos en los manuales y que nos hubieran ahorrado horas de trabajo. Recorre todo lo que es posible hacer con el IDE, desde la organización de proyectos hasta las extensiones o add-ins, pasando por el editor, la depuración, personalización del entorno, trucos de optimización, e incluso Visual Studio Tools for Office. Como curiosidad, en su sitio Web, pueden descargarse pequeños fragmentos en formato PDF (ver http://www.oreilly.com/catalog/visualstudiohks) 57 << dnm.desvan noticias.noticias Marino Posadas Presentado por primera vez un dispositivo de pantalla en 3D La empresa IO2 Technology (cuya Web estuvo colapsada desde pocos minutos después de producirse el anuncio oficial), ha presentado al público por primera vez un dispositivo de pantalla en 3 dimensiones. Los principios en los que se basa su funcionamiento son los del holograma láser que proyecta imágenes o vídeo proveniente de TV, DVD u ordenadores. Permite a las aplicaciones interactivas que lo manejen utilizando los dedos, en lugar del ratón. Para más datos, ver el sitio de IO2: http://www.io2technology.com/ dojo/204/v.jsp?p=/home. La noticia es independiente del anuncio por parte de Japón de una iniciativa a nivel nacio- Documentos y código en la Red Un vistazo a la seguridad en ASP.NET 2.0: Esa es la propuesta del artículo que J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley, Kishore Gopalan firman para MDSN y que está accesible en el sitio http://msdn.microsoft.com/library/default.asp?url=/library/enus/dnpag2/html/PAGPractices0001.asp. Un extenso documento que ha obtenido la mejores calificaciones de todos sus lectores, y que está siendo recomendado por los sitios más populares. EssentialXML Quick Reference: Guía rápida en formato PDF de la, más extensa, obra de Don Box y Aaron Skonnard, firmada por éste último y Martin Gudgin. Puede descargarse desde http://65.214.43.45/books/addisonwesley/EssentialXML/index.tss A Trustworthy Vision for Computing: El sitio Web oficial de Microsoft donde se explica la forma en que la compañía está siguiendo la iniciativa de Informática Fiable, y las prácticas que se llevan a cabo y se recomiendan o exigen en todos sus desarrollos. Disponible en http://www.microsoft.com/mscorp/twc/overview.mspx nal para crear un sistema de TV Digital que permita ver, tocar e incluso disponer de la capacidad de "oler" ambientes virtuales, en las que están implicados el propio gobierno japonés, algunas de las más relevantes universidades niponas y compañías del volumen de Matsushita y Sony (http://news.com.com/Japan+project+aims+to+create+3D+TV+by+2020/2100-1041_35839341.html?tag=nefd.top) Utilidades del mes Google desarrolla un add-in gratuito para Microsoft Word que permite la edición y publicación de blogs. El Add-in se intala (una vez descargado gratuitamente del sitio http://buzz.blogger.com/bloggerforword.html), fácilmente y una vez activo, presenta un menú adicional dentro de Word, con opciones de edición y publicación, guardado, control de borradores. Eso sí, requiere la creación de una cuenta personalizada en Blogger y como puede verse en la pantalla capturada después de su instalación, puede realizarse una previsualización del código HTML que se genera, previo a su publicación. Remora USB file guard Interesante utilidad gratuita que realizar copias de seguridad de los datos en USB con compresión/descompresión automática, y varias opciones de sincronización. Se puede descargar de http://www.richskills.com/products/6/freeversion.asp <<dotNetManía Sitios recomendados 58 The Server Side.NET: Uno de los sitios que desde su aparición acapara más visitas, movimiento y noticias de actualidad sobre .NET. Disponible en http://65.214.43.45/index.tss. Sitio Web de Rubén Vigón: Excelente sitio de este MVP de Visual Basic .NET con montones de artículos interesantes, recursos, código fuente, tutoriales, manuales y mucho más sobre .NET en general y VB.NET en particular. http://www.mvp-access.com/rubenvigon