<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang=""><title type="html">rjimenez</title><subtitle type="html" /><id>http://geeks.ms/blogs/rjimenez/atom.aspx</id><link rel="alternate" type="text/html" href="http://geeks.ms/blogs/rjimenez/default.aspx" /><link rel="self" type="application/atom+xml" href="http://geeks.ms/blogs/rjimenez/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.31106.3070">Community Server</generator><updated>2010-05-23T23:39:00Z</updated><entry><title>Big Data Spain 2012: CloudMC</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2012/12/04/big-data-spain-2012-cloudmc.aspx" /><id>/blogs/rjimenez/archive/2012/12/04/big-data-spain-2012-cloudmc.aspx</id><published>2012-12-04T19:38:00Z</published><updated>2012-12-04T19:38:00Z</updated><content type="html">&lt;p&gt;Hola,&lt;/p&gt;
&lt;p&gt;Hace un par de semanas estuve en el evento Big Data Spain 2012 presentando un peque&amp;ntilde;o proyecto que he venido desarrollando en mi tiempo libre en este &amp;uacute;ltimo a&amp;ntilde;o con un par de amiguetes. &lt;/p&gt;
&lt;p&gt;Acabo de leer el post de David Salgado sobre &amp;ldquo;Cuando el software retrasa la investigaci&amp;oacute;n&amp;rdquo; y no puede venir m&amp;aacute;s en la l&amp;iacute;nea. Coincido mucho en todas sus apreciaciones. Yo tambi&amp;eacute;n no paro de sorprenderme cuando mi curiosidad me lleva a sacarle a mis amigos todos los entresijos de sus trabajos, y veo como el software con el que tienen que lidiar les lastra una y otra vez. Y que muy pocas de las mejoras en nuestro terreno permean realmente en otras &amp;aacute;reas y, cuando lo hacen, es con muchos a&amp;ntilde;os de retraso.&lt;/p&gt;
&lt;p&gt;En este caso concreto, un buen amigo, radiof&amp;iacute;sico de profesi&amp;oacute;n, me coment&amp;oacute; sus malas experiencias ejecutando simulaciones de MonteCarlo para resolver problemas de transporte de radiaci&amp;oacute;n. Y el resultado pod&amp;eacute;is verlo en el v&amp;iacute;deo de la charla&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:437caba2-ca55-425c-9201-f84c05851877" style="padding-bottom:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;float:none;padding-top:0px;"&gt;
&lt;div&gt;&lt;a target="_new" href="http://www.youtube.com/watch?v=nb1dqiGH860&amp;amp;feature=plcp"&gt;&lt;img style="border-style:none;" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/video4cee2949a385_5F00_0CAB9B37.jpg" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207694" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author><category term="Azure" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/Azure/default.aspx" /><category term="BigData" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/BigData/default.aspx" /></entry><entry><title>[Video] Modeling and Code Generation on the .Net platform</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2012/06/28/video-modeling-and-code-generation-on-the-net-platform.aspx" /><id>/blogs/rjimenez/archive/2012/06/28/video-modeling-and-code-generation-on-the-net-platform.aspx</id><published>2012-06-28T08:35:00Z</published><updated>2012-06-28T08:35:00Z</updated><content type="html">&lt;p&gt;Hola! &lt;/p&gt;
&lt;p&gt;Acaban de publicar en InfoQ el &lt;a target="_blank" href="http://www.infoq.com/presentations/Modeling-and-Code-Generation-on-the-NET-Platform-at-Icinetic"&gt;v&amp;iacute;deo de la presentaci&amp;oacute;n&lt;/a&gt; que hice, junto con mi compa&amp;ntilde;ero Pedro J. Molina, en el &lt;a target="_blank" href="http://www.codegeneration.net/cg2012/index.php"&gt;Code Generation 2012&lt;/a&gt;, un evento que se celebra todos los a&amp;ntilde;os en Cambridge en el que se re&amp;uacute;nen las principales empresas interesadas en el Model-Driven Software Development. &lt;/p&gt;
&lt;p&gt;En nuestra presentaci&amp;oacute;n mostramos c&amp;oacute;mo usamos la plataforma .Net en Icinetic para construir herramientas de modelado y generaci&amp;oacute;n de c&amp;oacute;digo. B&amp;aacute;sicamente hicimos un recorrido sobre los aspectos a considerar a la hora de emprender el desarrollo de este tipo de herramientas, y revisamos los frameworks y utilidades que tenemos disponible en .Net sobre los que podemos apoyarnos para no hacerlo todo desde cero. &lt;/p&gt;
&lt;p&gt;Para finalizar mostramos un par de demos de nuestra implementaci&amp;oacute;n espec&amp;iacute;fica de MDSD (Radarc), generando dos peque&amp;ntilde;os ejemplos de aplicaciones basadas en NServiceBus y WP7, respectivamente.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.codegeneration.net/cg2012/images/CG2012logo600x171.gif" alt="Code Generation 2012" /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=205813" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author><category term="Video" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/Video/default.aspx" /><category term="MDSD" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/MDSD/default.aspx" /><category term="&amp;quot;Code Generation&amp;quot;" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/_2600_quot_3B00_Code+Generation_2600_quot_3B00_/default.aspx" /></entry><entry><title>[VSX] DTE How-to’s reunidos (I)</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2012/06/24/vsx-dte-how-to-s-reunidos-i.aspx" /><id>/blogs/rjimenez/archive/2012/06/24/vsx-dte-how-to-s-reunidos-i.aspx</id><published>2012-06-24T17:52:00Z</published><updated>2012-06-24T17:52:00Z</updated><content type="html">&lt;p&gt;Hola! Siguiendo la estela del gran Carlos Quintero, con su aut&amp;eacute;ntica &lt;a href="http://www.mztools.com/resources_vsnet_addins.aspx"&gt;enciclopedia online sobre Visual Studio Extensibility&lt;/a&gt; (que tantas horas nos ha ahorrado a algunos), intentar&amp;eacute; ir documentando algunas de la operaciones de VSX m&amp;aacute;s &amp;ldquo;tricky&amp;rdquo;. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5&gt;How-To: &amp;ldquo;Add Item As Link&amp;rdquo; programmatically&lt;/h5&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La operaci&amp;oacute;n sobre Visual Studio consiste simplemente en seleccionar &amp;ldquo;Add&amp;rdquo; &amp;ndash;&amp;gt; &amp;ldquo;Existing Item&amp;rdquo; sobre el elemento al que queremos agregar el link: &lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_6DC6B55D.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_76C31B11.png" width="244" height="148" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n buscamos el archivo que queremos agregar como link y seleccionamos &amp;ldquo;Add As Link&amp;rdquo; en el selector del bot&amp;oacute;n &amp;ldquo;Add&amp;rdquo;:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_13E8C31C.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_3FA8F13E.png" width="250" height="166" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Y listo. &lt;/p&gt;
&lt;p&gt;Pues bien, para hacer esto &amp;ldquo;programmatically&amp;rdquo; desde un package o una macro de VS, primero tenemos que obtener el &amp;ldquo;Project&amp;rdquo; o &amp;ldquo;ProjectItem&amp;rdquo; que albergar&amp;aacute; dicho link. Sobre c&amp;oacute;mo recorrer la estructura de proyectos y archivos de una soluci&amp;oacute;n hay documentaci&amp;oacute;n extensa, por ejemplo podemos consultar el siguiente &lt;a href="http://support.microsoft.com/kb/555561"&gt;recurso&lt;/a&gt;. Ambas interfaces, &amp;ldquo;Project&amp;rdquo; y &amp;ldquo;ProjectItem&amp;rdquo;, nos proporcionan una propiedad &amp;ldquo;ProjectItems&amp;rdquo; que representa la colecci&amp;oacute;n de sus elementos hijos en dicho &amp;aacute;rbol de soluciones. Sobre la colecci&amp;oacute;n &amp;ldquo;ProjectItems&amp;rdquo; podemos usar el m&amp;eacute;todo &amp;ldquo;AddFromFile&amp;rdquo;:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;hostProjectOrProjectItem.ProjectItems.AddFromFile(realPathOfTheLinkedFile);&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;Si el elemento est&amp;aacute; en la ruta correspondiente al &amp;ldquo;Project&amp;rdquo; o &amp;ldquo;ProjectItem&amp;rdquo; sobre el que estamos ejecutando el m&amp;eacute;todo, se agregar&amp;aacute; el archivo sobre Visual Studio normalmente. Si las rutas no coinciden, el elemento ser&amp;aacute; agregado como un link.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5&gt;How-To: Obtener el path de un archivo alojado en una carpeta de soluciones &lt;/h5&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En la mayor&amp;iacute;a de los casos si tenemos un &amp;ldquo;ProjectItem&amp;rdquo; de una soluci&amp;oacute;n y accedemos al m&amp;eacute;todo &amp;ldquo;get_FileNames(0)&amp;rdquo; obtendremos la ruta del fichero al que representa en VS.&lt;/p&gt;
&lt;p&gt;Sin embargo, si tenemos un &amp;ldquo;ProjectItem&amp;rdquo; cuyo padre es directamente una carpeta de soluciones como en este ejemplo:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_0E5A06DE.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_3EC06587.png" width="173" height="267" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;La llamada a get_FileNames(0) provocar&amp;aacute; una excepci&amp;oacute;n. En este caso concreto tendremos que hacer dicha llamada con index 1: get_FileNames(1)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5&gt;How-To: Crear un ProjectTemplate con links&lt;/h5&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el caso en que estemos creando plantillas de proyecto o soluci&amp;oacute;n que contengan links a rutas relativas, podemos ver como, al ser desplegadas, dichos links quedan rotos:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_1B43C122.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_7DDE438A.png" width="176" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Simplemente el problema es que apuntan a la ruta desde la que estamos desplegando la plantilla, en lugar de a la nueva ruta donde la nueva soluci&amp;oacute;n se ha creado. Para evitar este problema podemos usar el atributo &lt;a href="http://msdn.microsoft.com/en-us/library/ms247196.aspx"&gt;CreateInPlace&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_2869FE9B.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_2A0AA4A2.png" width="401" height="208" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Que nos permitir&amp;aacute; que los links se actualicen a la ruta de la nueva soluci&amp;oacute;n.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=205733" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author></entry><entry><title>[VS11] Los nuevos VSIX</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2012/03/15/vs11-los-nuevos-vsix.aspx" /><id>/blogs/rjimenez/archive/2012/03/15/vs11-los-nuevos-vsix.aspx</id><published>2012-03-15T09:45:09Z</published><updated>2012-03-15T09:45:09Z</updated><content type="html">&lt;p&gt;Hola!&lt;/p&gt;  &lt;p&gt;Seguro que muchos estáis ya probando la beta de Visual Studio 11. Yo también estoy sufriendo la atrofia en los conos de mi retina en detrimento de mis bastones, en claro estado de overflow... En el caso de que vayamos a probar los paquetes de extensión para Visual Studio (VSIX) lo primero es descargarnos el &lt;a href="http://www.microsoft.com/download/en/details.aspx?id=28990"&gt;SDK de Visual Studio 11&lt;/a&gt; Beta. Una vez instalado podemos seleccionar el tipo de proyecto &amp;quot;Visual Studio Package&amp;quot; bajo la categoría de &amp;quot;Other Project Types&amp;quot; en el menú &amp;quot;New Project&amp;quot;:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/clip_5F00_image002_5F00_154634B6.jpg"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="clip_image002" border="0" alt="clip_image002" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/clip_5F00_image002_5F00_thumb_5F00_5B9374FE.jpg" width="432" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Al igual que en Visual Studio 2010, lo primero que nos encontramos es un wizard para configurar el paquete, eligiendo el lenguaje a usar, namespace, proyectos de test, etc. Una vez finalizada esta preconfiguración Visual Studio generará nuestro paquete de extensión y nos mostrará su correspondiente manifiesto:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_38EF3683.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_5D341B05.png" width="429" height="303" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Podemos comprobar que aunque el estilo del diseñador del manifiesto ha cambiado, así como el namespace de su correspondiente xml, los elementos que se describen son los mismos. Tal como se definía en los paquetes de VS2010&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_615DF2CA.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_79DD6A4D.png" width="814" height="301" /&gt;&lt;/a&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_36A1C653.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_59062F41.png" width="442" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Se siguen definiendo los metadatos del paquete, las versiones de Visual Studio compatibles, las referencias que requiere el paquete y los artefactos que se van a instalar. En cuanto a esto último, el tipo de contenido instalable con un paquete, sí han habido pequeños cambios:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_4C1BB356.png"&gt;&lt;img style="background-image:none;border-right-width:0px;margin:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_434BAB0A.png" width="244" height="230" /&gt;&lt;/a&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_6C734348.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="image" border="0" alt="image" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_4962D1D8.png" width="343" height="229" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Se puede ver que ya no disponemos de los elementos “Custom Extension Type” y “Template Wizard”. El primero de ellos nos permitía crear extensiones VSIX para Visual Studio 2010 que a su vez podían ser extendidas por otras extensiones VSIX. Es decir, con esta opción podíamos crear paquetes VSIX que consumían otros paquetes VSIX, ambos manejados por el mecanismo de extensibilidad de Visual Studio, el Extension Manager. En el caso de las “Template Wizard”, nos permitían personalizar la creación de un nuevo proyecto o solución de Visual Studio a partir de plantillas de proyecto. Es el mecanismo que usa, por ejemplo, el propio proyecto de creación de VS Packages para que el usuario configure a modo de &lt;em&gt;wizard&lt;/em&gt; el lenguaje del paquete, su &lt;em&gt;namespace&lt;/em&gt;, sus proyectos de test, etc.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;En escenarios de migración, la teoría dice que el asistente de conversión debería hacer el trabajo por nosotros. Sin embargo, para mí lo más rápido y efectivo ha sido crear un nuevo proyecto de VSIX vacío desde el VS11 y migrar el contenido. Pero claro, ¿qué hacemos si tenemos contenido de tipo “Custom Extension Type” o “Template Wizard”?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Bueno, el caso de las “Custom Extension Type”, se trata de un escenario bastante particular que tendremos que resolver de una forma mucho más manual si queremos compatibilizar con VS11. En el caso de usar “Template Wizard”, es mucho más sencillo. Simplemente si teníamos un paquete VSIX que usaba “Template Wizard”, sustituimos el tipo de contenido por “Assembly”, con la referencia al ensamblado donde se encuentra la clase que implementa “Microsoft.VisualStudio.TemplateWizard.IWizard”, y listo, la “Template Wizard” funcionará en VS11.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203838" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author></entry><entry><title>DSL con diseñador WPF</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2011/01/03/dsl-con-dise-241-ador-wpf.aspx" /><id>/blogs/rjimenez/archive/2011/01/03/dsl-con-dise-241-ador-wpf.aspx</id><published>2011-01-03T09:00:00Z</published><updated>2011-01-03T09:00:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En los &amp;uacute;ltimos a&amp;ntilde;os la comunidad &lt;a href="http://www.netfxfactory.org/"&gt;NetFxFactory&lt;/a&gt; ha venido desarrollando art&amp;iacute;culos muy influyentes relacionados con las DSL Tools de Microsoft. Han aportado excelentes soluciones en temas como el multidiagrama o el uso de patrones en modelos. &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En Septiembre de 2009, publicaron &amp;ldquo;&lt;a href="http://www.netfxfactory.org/blogs/papers/archive/2009/09/20/provide-an-improved-user-experience-to-your-dsls.aspx"&gt;Provide an improved user experience to your DSL&amp;#39;s&lt;/a&gt;&amp;rdquo; en el que anticipaban una de las principales caracter&amp;iacute;sticas&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;incorporadas en la versi&amp;oacute;n de DSL Tools de 2010: los dise&amp;ntilde;adores basados en WPF; dando una primera aproximaci&amp;oacute;n para Visual Studio 2008. Una vez lanzado Visual Studio 2010 publicaron &amp;ldquo;&lt;a href="http://www.netfxfactory.org/blogs/papers/archive/2010/02/18/magnify-your-diagram.aspx"&gt;Magnify your diagram&lt;/a&gt;&amp;rdquo;, art&amp;iacute;culo en el que migraban su prototipo de 2008 haciendo uso de todas las caracter&amp;iacute;sticas lanzadas en la nueva versi&amp;oacute;n de DSL Tools. &lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Como bien dice Pascal Recchia, autor de estos art&amp;iacute;culos, a pesar de que entre estas nuevas caracter&amp;iacute;sticas no se propone ninguna mejora directa sobre los mecanismos de layout de los dise&amp;ntilde;adores generados (que supone, sin lugar a dudas, un de lde la herramienta) se puede entrever que la estrategia que se quiere seguir para afrontarlos es precisamente el uso de WPF.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En el ejemplo que se propone en dichos art&amp;iacute;culos se desarrolla un DSL para modelar una red de aeropuertos y vuelos entre aeropuertos. &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_0241A35E.png"&gt;&lt;img height="428" width="722" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_7B7E740D.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Un ejemplo bastante simple y &amp;ldquo;espec&amp;iacute;fico del dominio&amp;rdquo;. Indudablemente de eso se trata. No obstante, si lo que queremos es desarrollar un dise&amp;ntilde;ador basado en WPF algo m&amp;aacute;s completo y gen&amp;eacute;rico, que nos sirva de referencia tanto para crear un dise&amp;ntilde;ador de clases, como para un entidad-relaci&amp;oacute;n o un &lt;a target="_blank" href="http://pjmolina.com/cuip/" title="CUIP"&gt;CUIP&lt;/a&gt;, la cosa se nos queda algo corta.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Tampoco nos sirve de mucho la plantilla de DSL con dise&amp;ntilde;ador WPF que viene incluida en la instalaci&amp;oacute;n de las DSL Tools de VS2010. &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_7071215E.png"&gt;&lt;img height="303" width="410" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_430F8B8E.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En este caso, el dise&amp;ntilde;ador que se genera desde nuestro metamodelo es, en efecto, un formulario WPF&amp;hellip; pero bastante discreto:&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_239D34FB.png"&gt;&lt;img height="153" width="415" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_5620926D.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Por tanto, para poder empezar a crear DSLs &amp;ldquo;con sustancia&amp;rdquo; usando esta prometedora caracter&amp;iacute;stica, hay que hacerse con un buen ejemplo de dise&amp;ntilde;adores de diagramas en WPF.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En CodeProject hay una serie de cuatro art&amp;iacute;culos, con su correspondiente c&amp;oacute;digo, que desgranan paso a paso el desarrollo de un &lt;a href="http://www.codeproject.com/KB/WPF/WPFDiagramDesigner_Part4.aspx"&gt;dise&amp;ntilde;ador de diagramas basado en WPF&lt;/a&gt;. Si descargamos el c&amp;oacute;digo de ejemplo podemos ejecutar la aplicaci&amp;oacute;n y veremos algo como esto:&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_7EDBF7B6.png"&gt;&lt;img height="293" width="337" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_510E2EF1.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Nos decidimos a integrar estos ejemplos de CodeProject sobre un peque&amp;ntilde;o DSL de entidades con atributos generado con las DSL Tools. &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;A la hora de crearlo seleccionamos la plantilla &amp;ldquo;Minimal Language&amp;rdquo;.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_795D6145.png"&gt;&lt;img height="261" width="359" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_4397F61E.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&amp;iquest;Y por qu&amp;eacute; no usar la plantilla &amp;ldquo;Minimal WPF Designer&amp;rdquo; si lo que queremos es desarrollar un dise&amp;ntilde;ador WPF? Pues porque con la plantilla WPF no se nos permite definir, y por tanto generar, desde el metamodelo, lo relativo al dise&amp;ntilde;ador y al mapeo entre sus elementos y los correspondientes elementos del modelo. Esto merece una explicaci&amp;oacute;n un poco m&amp;aacute;s en profundidad.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Como vemos en la siguiente imagen, un metamodelo en DSL Tools est&amp;aacute; representado por dos partes: Elementos del modelo (Classes and relationships) y Elementos del diagrama (Diagram Elements). &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_27A6C126.png"&gt;&lt;img height="185" width="560" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_4BEBA5A8.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Mientras los primeros definen el dominio: entidades y atributos en nuestro ejemplo, aeropuertos y vuelos en el de NetFxFactory; los segundos definen la representaci&amp;oacute;n en un dise&amp;ntilde;ador de cada una de las instancias de los elementos de ese dominio, tanto en forma visual, como en posici&amp;oacute;n, tama&amp;ntilde;o o Zindex. Los peque&amp;ntilde;os conectores que relacionan ambas partes marcan el mapeo entre los elementos de las respectivas regiones, es decir, qu&amp;eacute; elemento de dise&amp;ntilde;ador representa a cada elemento del dominio.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Con la plantilla de dise&amp;ntilde;ador de WPF por defecto, que es la que se usa en el ejemplo de NetFxFactory, la parte de dise&amp;ntilde;ador esta deshabilitada, y no se nos permite mapear elementos de dise&amp;ntilde;ador a elementos de dominio. Esto implica que nuestro modelo s&amp;oacute;lo mantendr&amp;aacute; informaci&amp;oacute;n sobre los elementos del dominio y no de c&amp;oacute;mo se representan los mismos en el dise&amp;ntilde;ador. Asimismo el mecanismo de persistencia de esta informaci&amp;oacute;n de dise&amp;ntilde;ador queda deshabilitada, es decir, no tendremos el archivo &amp;ldquo;.diagram&amp;rdquo; en nuestro modelo y, por tanto, no se guardar&amp;aacute;n, entre otras cosas, las posiciones de los elementos en el dise&amp;ntilde;ador.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Por todas estas cosas utilizamos la plantilla &amp;ldquo;Minimal Language&amp;rdquo;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;y creamos nuestro DSL de entidades (Pod&amp;eacute;is ver el metamodelo en la imagen anterior).&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;A la soluci&amp;oacute;n creada le agregamos el proyecto que comentamos de los art&amp;iacute;culos de CodeProject. En este caso usamos el c&amp;oacute;digo que acompa&amp;ntilde;a al art&amp;iacute;culo 4. Previamente lo convertimos en biblioteca de clases y eliminamos el App.xaml que ya no necesitaremos.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_7AEDE17F.png"&gt;&lt;img height="276" width="273" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_71B1A63E.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En este punto, si ejecutamos la soluci&amp;oacute;n actual, obviamente vemos el dise&amp;ntilde;ador generado por defecto, basado en WinForms:&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_7C8E8786.png"&gt;&lt;img height="182" width="366" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_65EC393F.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Para usar nuestro nuevo dise&amp;ntilde;ador, basado en WPF, tenemos que a&amp;ntilde;adir algo de c&amp;oacute;digo &amp;ldquo;custom&amp;rdquo;. La responsabilidad del dise&amp;ntilde;ador recae sobre tres objetos: EditorFactory, DocData y DocView (se encuentran en la carpeta GeneratedCode del proyecto DslPackage). El objeto DocView corresponde a la interfaz del dise&amp;ntilde;ador, el DocData contiene la representaci&amp;oacute;n en memoria del documento y maneja el guardado y cargado del mismo, mientras el EditorFactory es el encargado de construir objetos de las dos anteriores clases. &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En este caso creamos una clase parcial del DocView para directamente cambiar la interfaz del dise&amp;ntilde;ador al &lt;i style="mso-bidi-font-style:normal;"&gt;Designer&lt;/i&gt; de WPF.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_720DB366.png"&gt;&lt;img height="213" width="201" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_426F94DA.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;En la clase parcial b&amp;aacute;sicamente sobrescribimos la carga de la vista y su contenido para albergar una instancia del &lt;i style="mso-bidi-font-style:normal;"&gt;WPF Designer&lt;/i&gt;.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="mso-tab-count:1;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;public&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:9.5pt;"&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;override&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt;&lt;/span&gt; Content&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="color:#0000ff;font-size:9.5pt;"&gt;get&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/span&gt; (content == &lt;span&gt;&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;content = &lt;span&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;&lt;/span&gt;.CreateControl();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/span&gt; content;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt;&lt;/span&gt; Wpf::&lt;span&gt;&lt;span style="color:#2b91af;"&gt;ContentControl&lt;/span&gt;&lt;/span&gt; WpfViewControl&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="color:#0000ff;font-size:9.5pt;"&gt;get&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;&lt;/span&gt;.Content != &lt;span&gt;&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;&lt;/span&gt;.Content &lt;span&gt;&lt;span style="color:#0000ff;"&gt;as&lt;/span&gt;&lt;/span&gt; Wpf::&lt;span&gt;&lt;span style="color:#2b91af;"&gt;ContentControl&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="color:#0000ff;font-size:9.5pt;"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="mso-tab-count:2;"&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-tab-count:1;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;global&lt;/span&gt;&lt;/span&gt;::System.Windows.&lt;span&gt;&lt;span style="color:#2b91af;"&gt;UIElement&lt;/span&gt;&lt;/span&gt; CreateControl()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-tab-count:1;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-tab-count:1;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt;&lt;/span&gt; DiagramDesigner.&lt;span&gt;&lt;span style="color:#2b91af;"&gt;Designer&lt;/span&gt;&lt;/span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-tab-count:1;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;override&lt;/span&gt;&lt;/span&gt; &lt;span&gt;&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&lt;/span&gt; LoadView()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;&lt;/span&gt;.LoadView();&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;global&lt;/span&gt;&lt;/span&gt;::System.Diagnostics.&lt;span&gt;&lt;span style="color:#2b91af;"&gt;Debug&lt;/span&gt;&lt;/span&gt;.Assert(&lt;span&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;&lt;/span&gt;.DocData.RootElement != &lt;span&gt;&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt;&lt;/span&gt; returnValue = &lt;span&gt;&lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/span&gt; (&lt;span&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;&lt;/span&gt;.DocData.RootElement != &lt;span&gt;&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;returnValue = &lt;span&gt;&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;WpfViewControl.DataContext = &lt;span&gt;&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;&lt;/span&gt;.DocData.RootElement;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;SelectionPusher.Add(WpfViewControl);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;&lt;span&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/span&gt; returnValue;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:9.5pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&lt;span style="font-size:9.5pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:normal;margin:0cm 0cm 0pt;mso-layout-grid-align:none;"&gt;&lt;span&gt;&lt;span style="font-family:Consolas;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Podemos comprobar el resultado si ejecutamos la instancia experimental y observamos el proyecto Debugging. Queda curioso, pero realmente a&amp;uacute;n no sirve para nada.&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_0DEEC292.png"&gt;&lt;img height="306" width="566" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_315B412A.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p align="justify" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;Para sacarle partido hay que meterse de lleno en el XAML de nuestro Designer y darle un par de vueltas. Pero por esto pasar&amp;eacute; a muy alto nivel, que para ense&amp;ntilde;ar XAML ya hay blogs mejores que &amp;eacute;ste. La base del dise&amp;ntilde;ador la podemos ver en el siguiente esquema:&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_3F6A0A5A.png"&gt;&lt;img height="470" width="584" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_30DEE868.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:block;float:none;margin-left:auto;margin-right:auto;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;La parte azulada corresponde a la interfaz del dise&amp;ntilde;ador, mientras la parte anaranjada corresponde a la infraestructura generada por las DSL Tools que lo sustenta.&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;El resultado es un DSL totalmente funcional con un dise&amp;ntilde;ador en WPF y del que, por ejemplo, podemos generar c&amp;oacute;digo mediante plantillas T4:&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_04FE6EAC.png"&gt;&lt;img height="411" width="762" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_4F390384.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:inline;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_2D3D7B33.png"&gt;&lt;img height="412" width="768" src="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/image_5F00_thumb_5F00_45143C8C.png" alt="image" border="0" title="image" style="background-image:none;padding-left:0px;padding-right:0px;display:inline;padding-top:0px;border-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p align="center" class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;&lt;span style="mso-fareast-language:es;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;El siguiente paso ser&amp;iacute;a sacar factor com&amp;uacute;n y obtener un conjunto de clases base m&amp;aacute;s un conjunto de plantillas para que, dada una definici&amp;oacute;n de un metamodelo cualquiera en un archivo DslDefinition, obtengamos el correspondiente dise&amp;ntilde;ador basado en WPF autom&amp;aacute;ticamente, tal y como se hace actualmente con los dise&amp;ntilde;adores basados en WinForms. &lt;/p&gt;
&lt;p class="MsoNormal" style="line-height:13pt;margin:0cm 0cm 10pt;"&gt;Este creo que es el camino en el que se est&amp;aacute;n centrando desde NetFxFactory&amp;hellip; estaremos atentos a sus resultados! &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=186685" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author><category term="T4" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/T4/default.aspx" /><category term="DSL" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/DSL/default.aspx" /><category term="WPF" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/WPF/default.aspx" /></entry><entry><title>DSL + UML = Pragmatic Modeling</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2010/09/03/dsl-uml-pragmatic-modeling.aspx" /><id>/blogs/rjimenez/archive/2010/09/03/dsl-uml-pragmatic-modeling.aspx</id><published>2010-09-03T06:52:00Z</published><updated>2010-09-03T06:52:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:11.6667px;"&gt;DSL + UML = Pragmatic Modeling es el t&amp;iacute;tulo de un &lt;a title="DSL + UML = Pragmatic Modeling" href="http://blogs.msdn.com/b/camerons/archive/2008/06/25/dsl-uml-pragmatic-modeling.aspx"&gt;art&amp;iacute;culo&lt;/a&gt;&amp;nbsp;de Cameron Skinner, General Manager del Visual Studio Ultimate team, en el
que relata la sinton&amp;iacute;a que intenta alcanzar Microsoft en cuanto a filosof&amp;iacute;a de
modelado y lo absurdo de las discusiones UML vs. DSL.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;En cuanto a esto, a lo absurdo del tema UML vs. DSL, el mejor que
conozco es uno titulado: &lt;a title="UML or DSL: Which bear is best? " href="http://msdn.microsoft.com/en-us/architecture/ff476944.aspx"&gt;&amp;ldquo;UML or DSL: Which bear is best?&amp;rdquo;&lt;/a&gt;.
En este se relata el gran paso que supone Visual Studio 2010 en la convivencia
entre UML y DSLs en el mundo Microsoft, quedando bien delimitada la estrategia
que a lo largo de tantos art&amp;iacute;culos nos hab&amp;iacute;an mostrado.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;No obstante, pasando al lado m&amp;aacute;s pr&amp;aacute;ctico del asunto, hemos
visto ejemplos de c&amp;oacute;mo generar c&amp;oacute;digo desde los modelos UML de modo similar a
como lo hac&amp;iacute;amos con los DSLs de DSL Tools, gracias al Visualization and
Modeling Feature Pack, pero no es tan f&amp;aacute;cil encontrar ejemplos pr&amp;aacute;cticos de
c&amp;oacute;mo manejar esta convivencia que comentamos entre modelos UML y DSLs. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;Un buen ejemplo para experimentar sobre esto me lleg&amp;oacute; a las
manos gracias a Pedro J. Molina, un experto en modelado y generaci&amp;oacute;n de c&amp;oacute;digo
que realiz&amp;oacute; su tesis sobre modelado de interfaces de usuario. Pod&amp;eacute;is visitar su
p&amp;aacute;gina en &lt;a title="PJMolina" href="http://pjmolina.com/es/"&gt;castellano&lt;/a&gt;&amp;nbsp;y en &lt;a title="PJMolina" href="http://pjmolina.com/metalevel/"&gt;ingl&amp;eacute;s&lt;/a&gt;.
Fruto de su investigaci&amp;oacute;n desarroll&amp;oacute; CUIP (Conceptual User Interfaces
Patterns), un metamodelo para la definici&amp;oacute;n de interfaces de usuario, cuyo
prototipo est&amp;aacute; implementado con DSL Tools. Dicho prototipo se compone realmente
de dos metamodelos: M8, un metamodelo de entidades de negocio y BizUI, que
define los patrones CUIP. Ambos metamodelos est&amp;aacute;n relacionados, de modo que si
en M8 tenemos Facturas y Clientes, en BizUI podremos definir una interfaz
Population de Facturas, que representar&amp;aacute; un listado de Facturas, o una interfaz
Service de Clientes, que representar&amp;aacute; un formulario para dar de alta un
cliente.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Al igual que en la mayor&amp;iacute;a de estas soluciones, se hace uso
de un DSL similar a los diagramas de clases de UML como base del modelado. Es
el peque&amp;ntilde;o truco que se usaba para suplir a UML en aplicaciones de modelado en
Visual Studio previas a la incorporaci&amp;oacute;n de UML. Incluso una de las plantillas
para generar DSLs en DSL Tools era (y sigue siendo) un diagrama de clases muy
similar al de UML. Sin embargo, con la llegada de Visual Studio 2010, esto
podr&amp;iacute;a empezar a cambiar. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;Mi idea inicial con CUIP era sustituir M8 por un diagrama de
clases de UML, con todas las ventajas que esto supondr&amp;iacute;a, y relacionarlo con
BizUI, el DSL de interfaces de usuario por medio del ModelBus. El ModelBus es
otra de las grandes novedades de Visual Studio 2010. B&amp;aacute;sicamente consiste en
una plataforma que nos permite referenciar elementos de modelo entre diferentes
modelos, independientemente de si corresponden al mismo metamodelo o a metamodelos
diferentes. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;Como veremos, si bien ModelBus es realmente &amp;uacute;til para
realizar estas labores entre DSLs, cuando intentamos atravesar la frontera y
aventurarnos con los nuevos modelos UML, el tema se nos escapa de las manos.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Vayamos por partes, antes de meternos con UML probaremos el
ModelBus para relacionar elementos de M8 y BizUI. En concreto intentaremos
asignarle a cada UI definida en BizUI una clase de M8. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;El proceso se compone de dos partes. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;El primero es habilitar el ModelBus en el metamodelo origen de
la relaci&amp;oacute;n, en este caso M8. En esta imagen podemos ver dicho metamodelo:&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl1.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl1.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;Simplemente bot&amp;oacute;n derecho sobre el dise&amp;ntilde;ador, elegimos el
comando &amp;lsquo;Enable ModelBus&amp;rsquo; y seleccionamos la opci&amp;oacute;n de exponer nuestro DSL al
ModelBus. &lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl2.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/250x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl2.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;El resultado ser&amp;aacute; un nuevo proyecto en nuestra soluci&amp;oacute;n con
un adaptador para consumir las referencias a cualquier elemento de dicho
metamodelo.&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl3.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/200x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl3.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;Para poder usar este metamodelo, con sus reci&amp;eacute;n creados adaptadores, instalamos el DSL transformando las plantillas de la soluci&amp;oacute;n, gener&amp;aacute;ndola y ejecutando el vsix
que obtenemos en el proyecto DslPackage.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;El segundo paso consiste en consumir los elementos expuestos
en el ModelBus por el M8. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;Para ello, vamos al metamodelo que referenciar&amp;aacute; a M8, en
este caso BizUI:&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl4.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/450x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl4.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Para definir las referencias a los elementos de M8 creamos propiedades de tipo
ModelBusReference. En nuestro ejemplo, definimos una propiedad llamada Class
en el elemento InteractionUnit (clase base de las UIs) que har&amp;aacute; referencia a la
clase sobre la que est&amp;aacute; definida dicha interfaz de usuario. &lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl5.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/130x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl5.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;Mediante esta propiedad podremos asignar, por ejemplo, una
clase Factura, creada en un modelo M8, sobre una UI Population creada en BizUI,
mediante el enlace s&amp;oacute;lido y persistente que nos proporciona ModelBus.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Una vez definidas las referencias instalamos el DSL como
hicimos con M8.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Con ambos metamodelos instalados, procedemos a probar las referencias
creadas en instancias de modelos de M8 y BizUI. Creamos un proyecto de prueba y a&amp;ntilde;adimos
un modelo de cada tipo:&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl6.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/200x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl6.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;A continuaci&amp;oacute;n abrimos el M8 y a&amp;ntilde;adimos un par de clases de
prueba:&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl7.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl7.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Guardamos el modelo M8 y creamos el modelo de interfaces de
usuario:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span style="font-size:11.6667px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl8.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl8.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Para definir la propiedad Class de las UIs, por ser de tipo
ModelBusReference, disponemos de un editor especial que nos permite definir
f&amp;aacute;cilmente el v&amp;iacute;nculo entre modelos que relacionar&amp;aacute; las UIs de BizUI y sus correspondientes clases de M8.
Simplemente indicamos el modelo que queremos referenciar, y qu&amp;eacute; elemento en
concreto dentro de ese modelo.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl9.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/350x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl9.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;En este caso, por ejemplo, hemos definido que
FacturaPopulation del modelo Facturacion.bizui referencia al elemento Factura de Facturacion.m8, as&amp;iacute; como
ClientePopulation, ClienteInstance y ClienteMasterDetail referencian al
elemento Cliente.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Una vez que tenemos ambos modelos relacionados, podremos
acceder a sus elementos y navegar por las propiedades ModelBusReference de uno
a otro gracias a los adaptadores.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Esto nos facilita un gran n&amp;uacute;mero de tareas arduas pero
frecuentes en los proyectos de modelado como validaciones cruzadas entre
metamodelos, definici&amp;oacute;n de modelos multidiagrama o accesos a diferentes modelos
en plantillas de generaci&amp;oacute;n de c&amp;oacute;digo. (Para esto &amp;uacute;ltimo necesitamos generar un
adaptador especial para el contexto de las T4, tal como se indica en este
&lt;a title="T4 Adapter" href="http://msdn.microsoft.com/en-us/library/ff817059.aspx"&gt;art&amp;iacute;culo&lt;/a&gt;)&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Por &amp;uacute;ltimo volvemos a la cuesti&amp;oacute;n que nos plante&amp;aacute;bamos
inicialmente&amp;hellip; &amp;iquest;por qu&amp;eacute; no usar UML en lugar de DSLs &amp;ldquo;pseudo-UML&amp;rdquo; como M8? &lt;/p&gt;
&lt;p class="MsoNormal"&gt;Pues s&amp;iacute;, podemos hacerlo. Simplemente agregamos un proyecto
de modelado a nuestra soluci&amp;oacute;n de ejemplo, y le agregamos un diagrama de clases
al que llamamos Facturacion.classdiagram:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl10.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/200x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl10.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;En Facturacion.classdiagram definimos las clases Factura y
Cliente, al igual que hicimos en M8:&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl11.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/500x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl11.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;Volvemos a nuestro modelo Facturacion.BizUI y modificamos las
propiedades Class de los elementos UI, para que apunten a las clases de nuestro
nuevo modelo UML. Simplemente volvemos a abrir el editor de ModelBusReference,
y elegimos el elemento de Facturacion.classdiagram que queremos referenciar en
cada caso:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl12.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/400x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl12.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;De este modo obtenemos nuestro modelo Facturacion.bizui con
las referencias correspondientes al diagrama de clases de UML
Facturacion.classdiagram:&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style="text-align:-webkit-center;"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl13.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/rjimenez/dsl13.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Hasta aqu&amp;iacute; todo f&amp;aacute;cil. Esto nos permitir&amp;iacute;a desechar DSLs como M8 que solapan contextos
en los que UML nos da completa expresividad y crear una convivencia &amp;ldquo;sana&amp;rdquo; con
DSLs que aporten donde realmente UML no llega, como es el caso de BizUI.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Pero como casi todo en la vida, esto tampoco es perfecto. Si
las referencias entre DSL y DSL mediante el ModelBus y los adaptadores nos
proporcionaban infinidad de ventajas en cuanto a generaci&amp;oacute;n de c&amp;oacute;digo,
validaci&amp;oacute;n de modelos, etc., en el caso de DSL - UML dichas ventajas no est&amp;aacute;n
tan accesibles.&amp;nbsp;&lt;span style="font-size:11.6667px;"&gt;El problema viene del hecho de que no podemos generar
adaptadores al ModelBus para modelos UML. Esto nos lo tendr&amp;iacute;a que proporcionar
Microsoft y, por ahora, no tienen planes de hacerlo, como bien nos coment&amp;oacute; en
&lt;a title="VSX Forum" href="http://social.msdn.microsoft.com/Forums/es-ES/vsarch/thread/3b7ed0a3-6811-41e5-a267-16af164d2920"&gt;este foro&lt;/a&gt; Alan Cameron Wills.
Ojal&amp;aacute; cambien de opini&amp;oacute;n&amp;hellip; estaremos expectantes :D&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=181430" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author><category term="ModelBus" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/ModelBus/default.aspx" /><category term="UML" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/UML/default.aspx" /><category term="DSL" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/DSL/default.aspx" /></entry><entry><title>Generando búsquedas mediante el patrón especificación</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2010/06/29/generando-especificaciones.aspx" /><id>/blogs/rjimenez/archive/2010/06/29/generando-especificaciones.aspx</id><published>2010-06-29T14:25:00Z</published><updated>2010-06-29T14:25:00Z</updated><content type="html">&lt;p&gt;Como ya coment&amp;eacute; en mi anterior post, llevo un tiempo trabajando sobre la arquitectura&amp;nbsp;&lt;a target="_blank" title="DDD NLayer" href="http://microsoftnlayerapp.codeplex.com/"&gt;DDD NLayer&lt;/a&gt;,&amp;nbsp;con el objetivo de generar gran parte de los artefactos que la componen a partir de modelos. En la soluci&amp;oacute;n de ejemplo ya se adjuntan ciertas plantillas T4 para generar las self-tracking entities y el context de EF. Sin embargo, hay bastante m&amp;aacute;s c&amp;oacute;digo &amp;quot;generable&amp;quot; que nos podr&amp;iacute;a servir de soporte y que nos permitir&amp;iacute;a r&amp;aacute;pidamente centrarnos en los procesos de negocio realmente complejos. Una de estas partes con posibilidad de ser f&amp;aacute;cilmente generable es la de las b&amp;uacute;squedas basadas en el patr&amp;oacute;n especificaci&amp;oacute;n. Para entender su implementaci&amp;oacute;n en DDD NLayer s&amp;oacute;lo hay que leer el &lt;a href="http://geeks.ms/blogs/unai/archive/2010/02/09/entity-framework-y-specification-pattern.aspx" title="Post de Unai"&gt;post&lt;/a&gt; de su autor Unai.&lt;/p&gt;
&lt;p&gt;La piedra angular de dicha implementaci&amp;oacute;n se basa en las clases Specification, que contienen los criterios de b&amp;uacute;squeda (m&amp;eacute;todo SatisfiedBy), junto a los par&amp;aacute;metros que se usan en dicha b&amp;uacute;squeda. Por ejemplo:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; BankAccountSearchSpecification
        :Specification&amp;lt;BankAccount&amp;gt;
    {
        &lt;span&gt;string&lt;/span&gt; _CustomerName;
        &lt;span&gt;string&lt;/span&gt; _BankAccountNumber;

        &lt;span&gt;public&lt;/span&gt; BankAccountSearchSpecification(&lt;span&gt;string&lt;/span&gt; bankAccountNumber, &lt;span&gt;string&lt;/span&gt; customerName)
        {
            _CustomerName = customerName;
            _BankAccountNumber = bankAccountNumber;
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;override&lt;/span&gt; System.Linq.Expressions.Expression&amp;lt;Func&amp;lt;BankAccount, &lt;span&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; SatisfiedBy()
        {
            Specification&amp;lt;BankAccount&amp;gt; spec = &lt;span&gt;new&lt;/span&gt; TrueSpecification&amp;lt;BankAccount&amp;gt;();

            &lt;span&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(_BankAccountNumber) &amp;amp;&amp;amp;
                !String.IsNullOrWhiteSpace(_BankAccountNumber))
            {
                spec &amp;amp;= &lt;span&gt;new&lt;/span&gt; BankAccountNumberSpecification(_BankAccountNumber);
            }
            &lt;span&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(_CustomerName) &amp;amp;&amp;amp;
                !String.IsNullOrWhiteSpace(_CustomerName))
            {
                spec &amp;amp;= &lt;span&gt;new&lt;/span&gt; DirectSpecification&amp;lt;BankAccount&amp;gt;(ba =&amp;gt; ba.Customer.ContactName.ToLower().Contains(_CustomerName.ToLower()));
            }

            &lt;span&gt;return&lt;/span&gt; spec.SatisfiedBy();
        }
    }&lt;/pre&gt;
&lt;p&gt;Nuestro objetivo es generar una clase Specification por cada entidad, que nos proporcione las b&amp;uacute;squedas parametrizadas b&amp;aacute;sicas sobre sus propiedades y relaciones. El problema es que en el caso de entidades con un n&amp;uacute;mero alto de propiedades, los constructores de estas clases Specification se llenar&amp;iacute;an de par&amp;aacute;metros. Una primera opci&amp;oacute;n ser&amp;iacute;a usar informaci&amp;oacute;n del modelo para obtener grupos de propiedades que formen especificaciones aut&amp;oacute;nomas dentro de cada entidad. As&amp;iacute; obtendr&amp;iacute;amos conjuntos de especificaciones como los que encontramos en la soluci&amp;oacute;n de&amp;nbsp;&lt;a title="DDD NLayer" href="http://microsoftnlayerapp.codeplex.com/releases/view/45211"&gt;DDD NLayer&lt;/a&gt;. Por ejemplo, para la entidad Order podemos encontrar OrderDateSpecification, OrderFromCustomerDateRangeSpecification,&amp;nbsp;OrderFromCustomerSpecification u&amp;nbsp;OrderShippingSpecification. Con esta soluci&amp;oacute;n ganamos en la ubicuidad del lenguaje que tanto buscamos en DDD, pero no conseguimos nuestro objetivo de definir b&amp;uacute;squedas de manera est&amp;aacute;ndar y simple si no poseemos el nivel de expresividad adecuado en nuestros modelos.&lt;/p&gt;
&lt;p&gt;Ese era nuestro caso, ya que part&amp;iacute;amos de un modelo similar al de Entity Framework o al modelo de clases de UML. Para estos casos podemos introducir un nuevo artefacto por cada entidad al que llamamos SearchValues, y que tiene la &amp;uacute;nica responsabilidad de encapsular los par&amp;aacute;metros de b&amp;uacute;squeda. De este modo, la clase Specification s&amp;oacute;lo tiene la responsabilidad de definir los criterios delegando el contenido de los par&amp;aacute;metros, como hemos dicho, a la clase SearchValues. En el constructor recibir&amp;aacute; un objeto de este tipo y en el m&amp;eacute;todo SatisfiedBy decidir&amp;aacute; si los par&amp;aacute;metros contenidos en ese objeto SearchValues cumplen o no con los criterios definidos.&lt;/p&gt;
&lt;p&gt;De modo que para cada entidad, por un lado generamos una clase SearchValues, con una propiedad por cada propiedad de la entidad (strings para tipos string, rangos para decimal, int o datetime, e int para filtrar por claves en relaciones), ademas de otra propiedad de tipo SearchValues para hacer b&amp;uacute;squedas por elementos que &amp;quot;no cumplan los criterios de ese otro SearchValues&amp;quot;, propiedad a la que llamamos NotInSearch. Y por otro lado generamos una clase Specification que contiene la correspondiente propiedad de tipo SearchValues y define los criterios de b&amp;uacute;squeda en el m&amp;eacute;todo SatisfiedBy a partir de los valores de esa propiedad. En c&amp;oacute;digo queda m&amp;aacute;s claro:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; BankAccountSearchSpecification
        :Specification&amp;lt;BankAccount&amp;gt;
    {
		&lt;span&gt;public&lt;/span&gt; BankAccountSearchValues SearchValues { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
				
                &lt;span&gt;public&lt;/span&gt; BankAccountSearchSpecification(BankAccountSearchValues searchValues)
                { 
			SearchValues=searchValues;
		}

               &lt;span&gt;public&lt;/span&gt; &lt;span&gt;override&lt;/span&gt; Expression&amp;lt;Func&amp;lt;BankAccount, &lt;span&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; SatisfiedBy()
               {
 			Specification&amp;lt;BankAccount&amp;gt; spec = &lt;span&gt;new&lt;/span&gt; TrueSpecification&amp;lt;BankAccount&amp;gt;();
				&lt;span&gt;if&lt;/span&gt;(SearchValues.CustomerName != &lt;span&gt;string&lt;/span&gt;.Empty)
				{
					spec &amp;amp;= &lt;span&gt;new&lt;/span&gt; DirectSpecification&amp;lt;BankAccount&amp;gt;(element =&amp;gt; element.CustomerName == (SearchValues.CustomerName));
				}
				&lt;span&gt;if&lt;/span&gt;(SearchValues.BankAccountNumber != &lt;span&gt;string&lt;/span&gt;.Empty)
				{
					spec &amp;amp;= &lt;span&gt;new&lt;/span&gt; DirectSpecification&amp;lt;BankAccount&amp;gt;(element =&amp;gt; element.BankAccountNumber == (SearchValues.BankAccountNumber));
				}
				&lt;span&gt;if&lt;/span&gt; (SearchValues.NotInSearch != &lt;span&gt;null&lt;/span&gt;)
                               {
                                       spec &amp;amp;= &lt;span&gt;new&lt;/span&gt; NotSpecification&amp;lt;BankAccount&amp;gt;(&lt;span&gt;new&lt;/span&gt; BankAccountSearchSpecification(SearchValues.NotInSearch));
                               }  
			
	        &lt;span&gt;return&lt;/span&gt; spec.SatisfiedBy();
        }
    }&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;    public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; BankAccountSearchValues
    {	
	&lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; CustomerName { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;;	}
	&lt;span&gt;public&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; BankAccountNumber	{ &lt;span&gt;get; &lt;/span&gt;&lt;span&gt;set; &lt;/span&gt;}
	&lt;span&gt;public&lt;/span&gt; BankAccountSearchValues NotInSearch { &lt;span&gt;get;&lt;/span&gt; &lt;span&gt;set;&lt;/span&gt; }
    }&lt;/pre&gt;
&lt;p&gt;Las expresiones que usamos para las b&amp;uacute;squedas por propiedades de tipos b&amp;aacute;sicos son triviales. En el c&amp;oacute;digo&amp;nbsp;anterior se pueden ver para tipos string por criterio de &amp;quot;igual a&amp;quot;. Otros criterios como &amp;quot;contenida en&amp;quot;, &amp;quot;menor que&amp;quot;, etc. son igualmente triviales, as&amp;iacute; como el uso de otros tipos como rangos de datetime, int, etc. En cuanto a las relaciones, la cosa se complica un poco cuando intentamos filtrar por extremos con cardinalidad &amp;quot;*&amp;quot; (Many). Por inercia la tendencia es usar una expresion del tipo:&lt;/p&gt;
&lt;p&gt;spec &amp;amp;= &lt;span&gt;new&lt;/span&gt; DirectSpecification&amp;lt;BankAccount&amp;gt;(element =&amp;gt; element.BankTransferFromThis.Contains(SearchValues.BankTransfer));&lt;/p&gt;
&lt;p&gt; Sin embargo, nos encontraremos con el error: &amp;quot;No se pudo crear un valor de constante de tipo &amp;#39;Namespace.Entities.Oferta&amp;#39;. S&amp;oacute;lo se admiten los tipos primitivos (&amp;#39;como Int32, String y Guid&amp;#39;) en este contexto&amp;quot;.&lt;/p&gt;
&lt;p&gt; La tendencia entonces cambia a crear el Join con Linq para filtrar por los elementos relacionados. El problema es que implicar&amp;iacute;a un severo golpe al dise&amp;ntilde;o y la simplicidad de este motor de b&amp;uacute;squedas. &lt;/p&gt;
&lt;p&gt;La soluci&amp;oacute;n&amp;nbsp;&amp;oacute;ptima&amp;nbsp;que encontramos fue usar Any(), con lo que se obtiene una forma elegante y simple de buscar en este tipo de relaciones, adem&amp;aacute;s de ser independiente de si se trata de &amp;quot;One to Many&amp;quot; o &amp;quot;Many to Many&amp;quot;. La sentencia quedar&amp;iacute;a as&amp;iacute;:&lt;/p&gt;
&lt;p&gt;spec &amp;amp;=&amp;nbsp;&lt;span&gt;new&lt;/span&gt;&amp;nbsp;DirectSpecification&amp;lt;BankAccount&amp;gt;(element =&amp;gt; element.BankTransferFromThis.Any(bt=&amp;gt;bt.BankTransferId==SearchValues.BankTransferId));&lt;/p&gt;
&lt;p&gt;Y la sentencia SQL que genera es algo como esto (un poco simplificada):&lt;/p&gt;
&lt;p&gt;SELECT *&amp;nbsp;FROM &amp;nbsp;BankAccount&lt;/p&gt;
&lt;p&gt;&lt;span&gt;	&lt;/span&gt;LEFT OUTER JOIN BankTransfer ON BankTransfer.BankAccountId = BankAccount.BankAccountId&lt;/p&gt;
&lt;p&gt;&lt;span&gt;	&lt;/span&gt;WHERE &amp;nbsp;EXISTS (SELECT&amp;nbsp;1&amp;nbsp;FROM BankTransfer&amp;nbsp;WHERE (BankTransfer.BankAccountId = BankAccount.BankAccountId) AND (BankTransfer.BankAccountId&amp;nbsp;= @p__linq__0)&lt;/p&gt;
&lt;p&gt;Una vez que hemos contemplado los casos de cada tipo diferente de propiedad, tanto si es escalar, como si es de navegaci&amp;oacute;n, s&amp;oacute;lo nos queda generar la plantilla que recorra las clases o entidades del modelo y vaya tratando cada uno de los casos comentados. Gracias a las T4, nos resultar&amp;aacute; f&amp;aacute;cil y s&amp;oacute;lo depender&amp;aacute; del metamodelo que estemos usando. En el caso de usar UML podemos seguir&amp;nbsp;&lt;a target="_blank" title="UML y T4" href="http://msdn.microsoft.com/en-us/library/ee329480.aspx"&gt;aqu&amp;iacute;&lt;/a&gt;&amp;nbsp;una gu&amp;iacute;a de c&amp;oacute;mo hacerlo, si queremos usar el modelo de EF podemos usar la gu&amp;iacute;a que suponen las plantillas de T4 para STE o POCO, y en el caso de que usemos modelos de DSL Tools simplemente al crear el proyecto de DSL Designer se nos crear&amp;aacute; un proyecto Debugging con ejemplos de dichas plantillas. No obstante, espero escribir alg&amp;uacute;n ejemplo de estas aproximaciones en pr&amp;oacute;ximos posts.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Algo que creo que deber&amp;iacute;amos tener en cuenta (y que siempre se ha de aplicar cuando usamos c&amp;oacute;digo generado) es que ni todas las b&amp;uacute;squedas se deber&amp;iacute;an de usar tal como nos la genera la plantilla desde el modelo, ni tampoco, por ello, deber&amp;iacute;amos crearlas todas &amp;quot;a mano&amp;quot;. Habr&amp;aacute; siempre zonas en nuestra aplicaci&amp;oacute;n, m&amp;aacute;s o menos amplias,&amp;nbsp;que puedan ser automatizadas. La cuesti&amp;oacute;n es encontrar la frontera correcta y no dejar de tener el control de qu&amp;eacute; est&amp;aacute; haciendo nuestro c&amp;oacute;digo por mucho que se haya generado autom&amp;aacute;ticamente. Por ejemplo, en soluciones basadas en self-tracking en que no disponemos de lazy loading, el hecho de cargar todas las colecciones (por medio de Include()) de todas las relaciones de nuestras entidades para luego poder usar este tipo de b&amp;uacute;squedas ya generadas autom&amp;aacute;ticamente mediante plantillas, nos tirar&amp;iacute;a abajo el rendimiento de ciertas partes de nuestra aplicaci&amp;oacute;n. Ni por ello debemos descartar usar las b&amp;uacute;squedas generadas para algunas otras partes de la aplicaci&amp;oacute;n, ni tampoco sacrificar al usuario por el hecho de usar ese c&amp;oacute;digo generado en todos sitios. De nuevo, como en muchas otras cosas, es cuesti&amp;oacute;n de sensatez y ponderaci&amp;oacute;n...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=178640" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author><category term="DDD" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/DDD/default.aspx" /><category term="EF" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/EF/default.aspx" /><category term="T4" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/T4/default.aspx" /></entry><entry><title>VSX, RAD &amp; Cloud</title><link rel="alternate" type="text/html" href="/blogs/rjimenez/archive/2010/05/23/vsx-rad-amp-cloud.aspx" /><id>/blogs/rjimenez/archive/2010/05/23/vsx-rad-amp-cloud.aspx</id><published>2010-05-23T22:39:00Z</published><updated>2010-05-23T22:39:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Aqu&amp;iacute; comienzo mi camino en este blog, agradeciendo en primer
lugar a Plain Concepts y en especial a Rodrigo Corral, por esta oportunidad de
expresi&amp;oacute;n en esta gran plataforma de referencia para buena parte del mundo .Net
en castellano.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Sobre qu&amp;eacute; intentar&amp;aacute;n aportar mis art&amp;iacute;culos ya adelanta algo
el t&amp;iacute;tulo de &amp;eacute;ste. En primer lugar, intentar&amp;eacute; dar una visi&amp;oacute;n un poco m&amp;aacute;s
cercana de c&amp;oacute;mo aprovechar las m&amp;uacute;ltiples posibilidades que nos brinda Visual
Studio 2010 para ser extendido con nuestros &amp;quot;plugins&amp;quot;. La irrupci&amp;oacute;n
de los paquetes VSIX, la adopci&amp;oacute;n de MEF y la explosi&amp;oacute;n de Visual Studio Gallery
como repositorio de extensiones, nos demuestran la fuerte apuesta de Microsoft,
ahora m&amp;aacute;s que nunca, por &lt;span&gt;&amp;nbsp;&lt;/span&gt;lograr que Visual
Studio sea realmente una plataforma de desarrollo f&amp;aacute;cilmente extensible. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Esta primera l&amp;iacute;nea tem&amp;aacute;tica navegar&amp;aacute; sobre otra, un poco m&amp;aacute;s
profunda y que me han inculcado desde que comenc&amp;eacute; con esto profesionalmente, y
es la de tendencias o metodolog&amp;iacute;as como Software Factories, desarrollo dirigido
por modelos, l&amp;iacute;neas de productos, generaci&amp;oacute;n de c&amp;oacute;digo, etc. En definitiva,
exprimir hasta la &amp;uacute;ltima gota de productividad de nuestras herramientas de
desarrollo.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Soy consciente de que hay mucha corriente en contra. Mucha
gente que prefiere los matices de Software Craftmanship y similares, y que
reusa de cualquier cosa que le impida escribir hasta el &amp;uacute;ltimo punto y coma de
su c&amp;oacute;digo. No obstante, mis ideas no son caprichosas. No son fruto de la
teor&amp;iacute;a, sino del pragmatismo m&amp;aacute;s extremo. Vivimos de servicios de software en
Andaluc&amp;iacute;a, sin inversores, sin padrinos pol&amp;iacute;ticos ni aliados poderosos. Es un
escenario maravilloso para la evoluci&amp;oacute;n, y ella es la que nos ha puesto estas
ideas en nuestras cabezas. Claro que nos encantar&amp;iacute;a poder escribir c&amp;oacute;digo como
el que pinta un cuadro, y disfrutar una a una de cada una de nuestras obras y
cuidar cada uno de sus detalles. Pero no podemos. Simplemente es fruto de la pura
supervivencia.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Actualmente trabajo en un proyecto que me ilusiona bastante
y del que creo que podr&amp;eacute; comentar cosas interesantes relacionadas con las
l&amp;iacute;neas que comento. Se trata del desarrollo de una herramienta en la onda de
Data Dynamics y WCF RIA Services pero que busca rellenar el hueco de sem&amp;aacute;ntica,
flexibilidad y extensibilidad que &amp;eacute;stas no cubren. El por qu&amp;eacute; no poder usar los
conceptos de alta productividad de estas herramientas en proyectos que
requieren de bases arquitect&amp;oacute;nicas mucho m&amp;aacute;s s&amp;oacute;lidas fue lo que nos empuj&amp;oacute; a
materializar esta iniciativa. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;A grandes rasgos, intentamos converger varias tecnolog&amp;iacute;as
Microsoft como plantillas de proyecto para definir arquitecturas, plantillas T4
para definir artefactos, y DSL Tools para definir modelos, para dar lugar a una
plataforma de desarrollo dirigido por modelos siguiendo las l&amp;iacute;neas que marcaron
Greenfield y Short en su libro Software Factories (&lt;a href="http://www.softwarefactories.com/TheBook.html"&gt;http://www.softwarefactories.com/TheBook.html&lt;/a&gt;).
Recientemente, y como prueba de fuego, usamos la arquitectura que est&amp;aacute;n
desarrollando C&amp;eacute;sar de la Torre y Unai Zorrilla, entre otros, (&lt;a href="http://microsoftnlayerapp.codeplex.com/"&gt;http://microsoftnlayerapp.codeplex.com/&lt;/a&gt;)
basada en la que propone Eric Evans en su libro &amp;ldquo;Domain Driven Design&amp;rdquo; (&lt;a href="http://domaindrivendesign.org/books"&gt;http://domaindrivendesign.org/books&lt;/a&gt;).
Si quer&amp;eacute;is ver alg&amp;uacute;n v&amp;iacute;deo de los resultados, s&amp;oacute;lo ten&amp;eacute;is que ped&amp;iacute;rmelo.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Entiendo que quiz&amp;aacute;s pueda chocar un poco la dualidad de
DDD&amp;rsquo;s: una arquitectura surgida de Domain Driven Design con este tipo de
herramientas m&amp;aacute;s afines al Data Driven Development. Sin embargo, encontramos
varios escenarios en los que la aleaci&amp;oacute;n de matices de ambos paradigmas puede
ser satisfactoria. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Detectamos, por ejemplo, clientes en estados de baja madurez
tecnol&amp;oacute;gica que, pese a que concentran procesos de negocio relativamente
complejos o cambiantes, no tienen capacidad financiera, o consideran demasiado
costoso y prescindible emprender una soluci&amp;oacute;n acorde a sus necesidades. Una
soluci&amp;oacute;n que conllevar&amp;iacute;a, si somos partidarios de Eric Evans, un proceso de
desarrollo inmerso en un lenguaje ubicuo, que resultara en una capa de dominio
que plasme fielmente los procesos del negocio. Todo ello sobre una arquitectura
que permita que el negocio evolucione sin interferencias tecnol&amp;oacute;gicas de ning&amp;uacute;n
tipo, entre otras cosas. Obviamente todo esto tiene un coste. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Normalmente el contraste de intereses entre ambas partes
hace inviable el proyecto. Una soluci&amp;oacute;n intermedia que se puede aportar es usar
herramientas de alta productividad&lt;span&gt;&amp;nbsp; &lt;/span&gt;tipo
RAD (como las que antes coment&amp;eacute;) para crear un producto intermedio, no
demasiado ambicioso, que pueda despertar el inter&amp;eacute;s tecnol&amp;oacute;gico del cliente, y
con el que pueda medir fielmente el aumento de productividad que le supone con
respecto a, por ejemplo, las herramientas de ofim&amp;aacute;tica. Sin embargo, es
evidente que hay un lado oscuro en este tipo de soluciones. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;El bajo grado de madurez de este tipo de clientes implica
procesos de negocio muy cambiantes. A su vez, la base arquitect&amp;oacute;nica del
producto desarrollado con herramientas RAD no es adecuada para entornos con
alto nivel de complejidad&lt;span&gt;&amp;nbsp; &lt;/span&gt;y/o cambio.
Esto hace que, si bien solemos conseguir despertar el inter&amp;eacute;s en el cliente por
desarrollarse tecnol&amp;oacute;gicamente, nos volvemos a enfrentar a un conflicto de
intereses. Conflicto que viene dado porque el cliente no suele asumir los altos
costes de una refactorizaci&amp;oacute;n completa del producto, desde el nivel
arquitect&amp;oacute;nico, lo cual resulta imprescindible para mantener el evolutivo junto
al aumento de inter&amp;eacute;s por seguir perfeccion&amp;aacute;ndolo. &lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Es aqu&amp;iacute; donde creo que una herramienta que ponga unas bases
arquitect&amp;oacute;nicas s&amp;oacute;lidas, con los par&amp;aacute;metros de alta productividad de las
herramientas RAD puede ser &amp;oacute;ptima. No obstante, hay otros escenarios que se
encuentran mucho m&amp;aacute;s exhaustivamente estudiados en los que tambi&amp;eacute;n pueden ser
eficientes estas herramientas, como l&amp;iacute;neas de productos en dominios verticales, prototipado real
r&amp;aacute;pido, normalizaci&amp;oacute;n de desarrollos en factor&amp;iacute;as, etc.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Por &amp;uacute;ltimo, siguiendo una l&amp;iacute;nea metodol&amp;oacute;gica parecida que adem&amp;aacute;s aprovecha las nuevas oportunidades que nos ofrece el Cloud Computing, me
encuentro enfrascado en otro proyecto bastante innovador, sobre el que espero
escribir alg&amp;uacute;n art&amp;iacute;culo. Se trata de usar la plataforma Windows Azure para aprovechar
su poder de paralelizaci&amp;oacute;n en la generaci&amp;oacute;n de c&amp;oacute;digo. De este modo se pueden
construir servidores de generaci&amp;oacute;n de modo que el cliente modele en local y use
Azure para generar los artefactos correspondientes, totalmente en paralelo. El
proyecto a&amp;uacute;n est&amp;aacute; en fases tempranas de desarrollo, sin embargo, ya hemos
encontrado bastantes temas interesantes que ir&amp;eacute; relatando a medida que vaya teniendo
tiempo.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;Y poco m&amp;aacute;s, ya s&amp;oacute;lo queda ponerse manos a la obra. Al l&amp;iacute;o!!&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=177202" width="1" height="1"&gt;</content><author><name>rjimenez</name><uri>http://geeks.ms/members/rjimenez/default.aspx</uri></author><category term="VSX" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/VSX/default.aspx" /><category term="RAD" scheme="http://geeks.ms/blogs/rjimenez/archive/tags/RAD/default.aspx" /></entry></feed>