
Tuesday, June 05, 2007
MMmm... un post en un blog del cual se ha hecho dispose() debería lanzar una InvalidBlogException? Interesante reflexión que queda aquí.
Bueno, mientras espero a ver si en un futuro (no muy lejano si hay algún Ummon por aquí), tengo más tiempo libre y cosas interesantes que contar, y reprendo el blog os dejo enlaces de algunos de los blogs de compañeros míos en raona:
- El blog de Ramón Bosch
- El blog de Oriol Quinquillá
- Res Cogitans (de Edin)
Aprovecho también para decir que si no pasa nada raro, participaré en seminario organizado por raona, sobre .NET 3.0 y aplicaciones financieras. Si estáis interesados, pasaros por http://www.raona.com/Seminarios2007/NET20NET30EVOLUTIONinFinantialIT/tabid/261/Default.aspx y nos vemos el 20 de Junio en Madrid o el 21 en Barcelona... Y tomamos unas cervecitas :)
Saludos.

Thursday, May 10, 2007
Pues eso... este blog se muere.
Últimamente no he tenido tiempo de actualizarlo, y por motivos personales voy a tener muy poco en los meses venideros.
No voy a dejar al pobre blog agonizando, así que prefiero que este sea el punto y final.
Por mi parte ha sido divertido y un placer... seguiré leyendo clearscreen :)
Un saludo,
edu

Wednesday, November 15, 2006
Bueno... Ahora que el .NET Framework 3.0 ya es oficial, pienso que es el momento de plantearse algunas reflexiones.
Años atrás, por allá el 2004, cuando Vista todavía era Longhorn se nos comentaban los tres grandes pilares sobre los qualses se sustentaría el nuevo sistema operativo: Indigo, Avalon y WinFS. Al cabo de poco tiempo supimos que WinFS desaparecería del sistema (aunque parte de su funcionalidad se incorporaría, aunque basada más en un index server o similar que en SQL Server). Recuerdo por aquellos tiempos un foro de arquitectos celebrado en Madrid, el año 2005 (no recuerdo exactamente cual). Hablaron primero Bill Gates en persona (sobre lo maravilloso que sería el mundo con Longhorn), luego creo recordar alguien de Informática el Corte Inglés nos comentó sobre un Framework que habían elaborado para trabajar en .NET y finalmente Catherine Heller habló sobre la filosofía de Smart Client. Bueno, el caso es que antes de que hablara el amigo Bill, alguien de Microsoft España, comentó que en Longhorn habían girado la tortilla: si el .NET Framework se había construído sobre Windows, dijo, la nueva versión de Windows se había construído sobre el .NET Framework. Y que la nueva API de Longhorn se llamaba WinFX y era enteramente managed. Bueno, la verdad es que por más increíble que sonara esa frase, la dijo muy serio y convencido y estoy seguro que alguien se lo creyó.
A la postre se demostró que era falso, claro. No pasó mucho tiempo que después de anunciar el enésimo retraso de Vista, para calmar al personal dijeron que Avalon e Indigo estarían en también en XP y que de paso iban a perder esos nombres tan molones y pasarían a llamarse Windows Presentation Foundation y Windows Communication Foundation. En aquel momento empezaron a surgir las primeras dudas: que aportará de nuevo Longhorn (o ya era Vista?) si de sus tres nuevos pilares fundamentales uno ya no está y los otros dos también estaran en XP?
Y finalmente hace poco el cambio de nombre: para no marear la perdiz WinFX se llamaría .NET Framework 3.0 (la verdad es que había cierta confusión sobre que versión de Frameork se incluiría con Vista) y ahora, hace nada, el anuncio que el .NET Framework 3.0 ya es oficial.
Hasta ahí la historia un poquillo resumida. Mis preguntas básicamente son... que pasará con .NET cuando salga Vista? Me explico: Vista incorpora bastantes novedades (sí, sí, al final se quedó sin la exclusiva de WinFS, Avalon e Indigo pero trae cosas muy interesantes), pero de momento sólo estan disponibles via código nativo. Por ejemplo, para interactuar con el Restart Manager, o para efectos de Aqua (como transperencias) o para acceder a las nuevas Dialog Boxes se tiene que llamar a P/Invoke. Básicamente al salir .NET Framework 3.0 en XP y 2003 todas las novedades exclusivas de Vista han quedado fuera del .NET Framework. Y que hará Microsoft a partir de ahora? Va a seguir excluyendo todas esas novedades del .NET Framework? Me gustaría poder programar una aplicación completamente en código manejado, sin tener la necesidad de llamar a P/Invoke para poder aprovechar todas las novedades de Vista (repito, algunas muy interesantes). Hasta ahora, en código nativo, cuando MS sacaba un nuevo Windows, se limitaba a añadir (de forma completamente desordenada, por cierto) un nuevo conjunto de funciones con el API nuevo. Era responsabilidad del desarrollador comprobar que la versión de Windows sobre la que se estaba ejecutando el programa contenía la función del API que se quería llamar. Pero con el .NET Framework (al menos de momento) eso no es así: yo programo un sistema con el Framework 3.0 y espero que funcione en cualquiera sistema que tenga el Framework 3.0 instalado... Como lo hará Microsoft para incorporar todas las novedades de Vista al .NET Framework sin romper la compatibilidad con sistemas anteriores? Es más... lo hará?
En fin... sólo son reflexiones de media mañana...
Un saludo ;-)

Monday, October 02, 2006
Si habéis probado de serializar un objeto que implemente IDictionary os habréis dado cuenta de que el sistema genera una excepción, indicando que no sabe como serializar dichos objetos.
Por suerte existe una solución bastante fácil (explicada tanto aquí como aquí): implementar la interfaz IXmlSerializable. En los métodos ReadXml ponemos el código para deserializar y en WriteXml el código de serializar.
A continuación un ejemplo (el mérito no es mío, si no de los que han hecho los enlaces anteriores, yo lo único que he hecho ha sido adaptarlo para que use genéricos). Los objetos de la clase SerializableDictionary se pueden serializar a Xml de la manera tradicional. Para más información pasaros por los enlaces anteriores ;-)
public class SerializableDictionary : Dictionary, IXmlSerializable
{
const string NS = <A HREF="">http://blogs.clearscreen.com</A>;
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader r)
{
XmlSerializer keySer = new XmlSerializer(typeof(K));
XmlSerializer valueSer = new XmlSerializer(typeof(V));
r.Read();
r.ReadStartElement("dictionary", NS); while (r.NodeType != System.Xml.XmlNodeType.EndElement)
{
r.ReadStartElement("item", NS);
r.ReadStartElement("key", NS);
K key = (K)keySer.Deserialize(r);
r.ReadEndElement();
r.ReadStartElement("value", NS);
V value = (V)valueSer.Deserialize(r);
r.ReadEndElement();
this.Add(key, value);
r.ReadEndElement();
r.MoveToContent();
}
r.ReadEndElement();
}
public void WriteXml(System.Xml.XmlWriter w)
{
XmlSerializer keySer = new XmlSerializer(typeof(K));
XmlSerializer valueSer = new XmlSerializer(typeof(V));
w.WriteStartElement("dictionary", NS); foreach (K key in this.Keys)
{
w.WriteStartElement("item", NS);
w.WriteStartElement("key", NS);
keySer.Serialize(w, key);
w.WriteEndElement();
w.WriteStartElement("value", NS);
V value = this[key];
valueSer.Serialize(w, value);
w.WriteEndElement();
w.WriteEndElement();
}
w.WriteEndElement();
}
#endregion
}
Editado @ 04/10: Eliminados unos molestos saltos de línea que impedían leer bien el código fuente... ^_^

Thursday, September 28, 2006
Pues eso... hay varias cosas que no me terminan de cuadrar sobre el como funciona el DataGridView cuando se vincula (mmm... ata?), cuando se hace data-binding para entendernos contra un objeto de negocio propio.
Supongamos que tengo la siguiente clase:
public class Activity
{
private Action _exitAction;
private bool _endStateActivity;
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public bool EndActivity
{
get { return _endStateActivity; }
set { _endStateActivity = value; }
}
[TypeConverter(typeof(ActionTypeConverter))]
public Action EntryAction
{
get { return _enterAction; }
set { _enterAction = value; }
}
}
La clase Action no importa para lo que quiero contar, imaginaosla como querais... podemos suponer que tiene una propiedad Name de tipo String.
Tengo también otra clase llamada State que entre otras cosas tiene una propiedad de tipo List, llamada Activities.
Creo un object data binding: Data -> Add New DataSource -> Object y selecciono la clase State.
Eso me crea un object data binding parecido a ese:
(Nota: En mi caso la clase Activity tiene también propiedades DoAction y ExitAction que son de tipo Action)
Luego, arrastro la propiedad Activities en un form, y me aparece automáticamente un dataviewgrid vinculado. Hasta ahí todo perfecto.
Ahora empieza la pesadilla... Cual es mi idea? Tengo varios tipos de Acciones que se pueden asignar a la propiedad EntryAction. Desde la grid vinculada me gustaría que se desplegara una combo con los distintos tipos de acciones que admito (p.ej. PlaySound y PlaySequence). Cuando el usuario escoja un valor de la combo, el datagridview debería crear un objeto Action, concreto (bueno, de hecho me gustaría que creara un objeto de una cierta clase derivada de Action. Si el usuario escoje PlaySound en la combo quiero que se cree un objeto de la clase PlaySound).
El primer paso es sencill En la DataGridView indico que quiero modificar las columnas y indico que la columna EntryAction es de tipo DropDownList. La cosa queda més o menos así:

Luego añado dos items a la columna EntryAction (dos cadenas) con los valores "PlaySound" y "PlaySequence" para que el usuario pueda escojer.
Finalmente creo la clase ActionTypeConverter que deriva de TypeConverter cuya finalidad es convertir una cadena a un objeto Action y viceversa. Defino los métodos:
public
override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
public
override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
public
override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
public
override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
Lo hago para que el CanConvertFrom y el CanConverTo indiquen true sólo si se desea convertir desde/a cadena e implemento el ConvertFrom para que devuelva una instancia de PlaySound o PlaySequence en función de si la cadena pasada es "PlaySound" o "PlaySequence". Finalmente el método ConvertTo hace lo contrario (devuelve una cadena "PlaySound" o "PlaySequence".
Ejecuto el programa y cuando escojo un valor de la combo:

Además ese error se repite ad-eternum cada vez que la DataViewGrid necesita refrescarse.
Tras unas cuantas lecturas por foros y demás, viendo que ese error se da un muchos casos, observo depurando que los métodos CanConvertFrom y ConvertFrom del ActionTypeConverter, pero los que convierten de Action a string no. Eso me extraña puesto que yo daba por supuesto que:
- La Grid llamaría a ConvertTo para pasar el objeto Action a una cadena y mostrar ese valor en la combo
- La Grid llamaría a ConvertFrom cuando se hubiese seleccionado un valor de la combo, para obtener un objeto Action (o en mi caso un objeto derivado de Action).
Pero, por alguna razón el punto (1) no se lleva a cabo... :(
Luego también me llamó la atención el hecho de que en unos foros se mencionaba que una celda de tipo combo en la grid sólo podía mostrar valores que contuviera la propia combo, y me asaltó la duda... no estará comparando por Equals? En este caso el mensaje de error, tendría sentido puesto que en la combo había cadenas (String) que nunca serían iguales a objetos Action (aunque yo proporcionase un ConvertTo que por alguna oscura razón no se llamaba). Así que hice dos cosas: poblar la combo (myColumn.Items.AddRange(...)) con dos objetos Action (un PlaySound y un PlaySequence) y redefnir los métodos Equals de forma que todos los PlaySound sean iguales entre ellos y todos los PlaySequence sean iguales entre ellos.
Cuando ejecuté el programa en la combo no aparecía el nombre "PlaySound" o "PlaySequence" sinó el nombre completo de la clase... tal y como lo hace el ToString(), así que ya puestos lo redefiní también (total... me hacía falta un método para pasar de Action a cadena, no?).
Y al ejecutar... funcionó! En la combo se mostraba "PlaySound" y "PlaySequence" y al seleccionar un valor, se ejecutaba el ConvertFrom del TypeConverter.
Mis dudas principales son:
- Por qué la Grid es capaz de ejecutar el ConvertFrom del TypeConverter para obtener un objeto a partir de la cadena y no es capaz de ejecutar el ConvertTo para obtener una cadena a partir del objeto (será porque todos los objetos tienen ToString() ?)
- Por qué me obliga a poblar la columna usando objetos Action en lugar de cadenas? (Aunque bueno, esto segundo lo puedo llegar a entender pienso que debería ser posible poblar la combo con cadenas que fuesen representaciones válidas de objetos de negocio y que la grid fuera lo suficientemente lista como para espavilarse).
En fin, tu... que líos...
Editado @28/09: Vale... creo que ya se cuando llama al ConvertTo y cuando llama al ToString(): Para poblar la combo necesita cadenas, así que llama al ToString(). Si tengo eso:
Action a1 = new PlaySound("foo");
Action a2 = new PlaySequence("bar");
col.Items.AddRange(a1, a2);
Para poblar la combo llamará a a1.ToString() y a2.ToString().
Luego el ConvertTo lo llama cuando lee de la fuente de datos, y la cadena resultante es la que intenta mostrar en la combo.

Thursday, August 10, 2006
No me refiero a si las letras salen tan pequeñas por la pantalla que ni se ven (toma chiste malo) si no a si un determinado hardware es compatible con una determinada version de Windows Vista... La gente de iexbeta mantienen una lista de hardware (y software) compatible con cada versión de Windows Vista. Por ejemplo, si tu tarjeta gráfica no funciona bien en la beta 2, a lo mejor puedes comprobar si funcionaria bien con la última build de Vista (la 5472 cuando escribo esto).
En http://www.iexbeta.com/wiki/index.php/Windows_Vista teneis todas las versiones de Vista con sus listas de compatibilidad.
Por cierto... hablando de esto... alguien ha conseguido instalar la beta 2 (build 5384) en un Latitude D820 con una nVidia Quadro NVS 110M y una Broadcom? Yo la verdad entre pantallazos azules, casques del internet explorer y colgadas del explorer estoy que ya no aguanto mas... (** un emoticono de llorar va aquí **)

Tuesday, July 11, 2006
Buenas!
Para "celebrar" :p que estoy haciendo cosillas con MDX (Managed DirectX) he abierto un blog sobre MDX. Lo podeis encontrar en http://burbujasmdx.blogspot.com/ y responde al original nombre de "Burbujas en MDX"...
La razón para separarlo en otro blog, y no ponerlo en este de Clearscreen, es porque me gustaría que este blog de Clearscreen fuese un reflejo de mi actividad profesional (aunque ahora por necesidades de proyecto estoy un poco alejado de .NET)... aunque si todo va bien espero poder meterme de lleno en .NET dentro de poco...
Un saludo a todos ;-)

Monday, April 10, 2006
Buenas... seguro que la mayoría de vosotros habéis trabajado, o conocéis los conceptos fundamentales de Ajax...
Pues bien, en el siguiente blog se habla del siguiente paso, al que llaman Comet:
http://alex.dojotoolkit.org/?p=545
Básicamente, la idea de Comet es que el servidor web pueda informar de ciertos eventos al cliente, SIN que haya por en medio una petición del cliente al servidor. Es decir, nos olvidamos de arquitecturas de polling y pasamos a una arquitectura de pushing.
Evidentemente Comet necesita de ajustes a realizar en los servidores web, puesto que mantener un socket abierto por cada cliente conectado no es muy escalable que digamos...
Saludos!

Thursday, February 09, 2006
Estos días he estado preparando una presentación, para la gira de presentación de VS2005 en barcelona. En concreto la demo mostraba las mejoras en winforms (clickonce, el nuevo data-binding) y un poquillo de team system: las herramientas de análisis de rendimiento.
Para preparar la demo he utilizado una máquina virtual, con todo el entorno montado (VS2005 Team System, Team Foundation Server, SQL Server 2005). Todo ha funcionado perfectamente excepto las herramientas de monitorización de rendimiento. Al intentar crear un test de rendimiento me ha salido una messagebox con el error "Not allowed on virtual machine".
Nada especialmente crítico pero siempre va bien saberlo... ;)

Wednesday, February 08, 2006
Todos los que hagáis desarrollado alguna aplicación web (sea con ASP.NET o con cualquier otra tecnología), habreis sufrido la compatibilidad entre los distintos navegadores. Anteriormente eran sólo problemas de javascript, pero ahora se unen las distintas interpretaciones de CSS que cada navegador realiza.
Si Miguel comentaba en este post que IE7 Beta 2 Preview no era compatible con determinados hacks CSS de IE6 (y IE7 Beta 1) y que muchas aplicaciones que funcionaban bien en IE6 no lo hacen en IE7 Beta 2, algo parecido ha sucedido entre Firefox 1.0.x y Firefox 1.5. Firefox 1.5 es ahora más estándar pero a costa de que determinadas páginas que se veían bien en Firefox 1.0.x dejen de verse bien en Firefox 1.5.
En una aplicación en la que estoy desarrollando nos ha sucedido esto, y nos hemos visto en la necesidad de detectar el navegador desde javascript, para poder modificar determinados estilos y hacer que la página se vea "bien" en todos los navegadores. Os paso el código de la función por si os interesa. Sólo distingue entre "internet explorer", "opera", "Firefox 1.0.x" y "Firefox 1.5". Está probada en IE6, Opera 8.02, Firefox 1.0.5 y Firefox 1.5. No puedo asegurar como se comporta con versiones anteriores o posteriores de los navegadores.
Para detectar el navegador no utiliza navigator.appName, sinó que comprueba que ciertos objetos javascript propios de cada navegador existan o no...
function detectBrowser() {
var ie = document.all != undefined;
var opera = window.opera != undefined;
if (opera) return "opera";
if (ie) return "ie";
if ((window)&&(window.netscape)&&(window.netscape.security)) {
if (window.XML) {
return "firefox15";
}
else return "firefox10";
}
return "ie"; // Si no sabemos que navegador es, devolvemos ie.
}