<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : Generaci&amp;#243;n de C&amp;#243;digo</title><link>http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx</link><description>Tags: Generaci&amp;#243;n de C&amp;#243;digo</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Generando un modelo desde la base de datos usando AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2009/12/02/generating_2D00_a_2D00_model_2D00_from_2D00_the_2D00_database_2D00_using_2D00_ajgenesis.aspx</link><pubDate>Wed, 02 Dec 2009 11:46:06 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1743328</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1743328</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/12/02/generating_2D00_a_2D00_model_2D00_from_2D00_the_2D00_database_2D00_using_2D00_ajgenesis.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://ajgenesis.codeplex.com" target="_blank"&gt;AjGenesis&lt;/a&gt;, mi proyecto open source de generación de código, usa tareas, templates (plantillas) y un modelo de libre definición, para generar artefactos de texto, en general código fuente, pero también archivos cualesquiera, como configuraciones, definición de proyectos, etc. Muchos de los ejemplos que están en el proyecto y otros que publiqué aparte, usan modelos serializados como archivos XML o de texto. Pero el modelo inicial puede ser cualquier entrada: no sólo esos archivos, sino cualquier fuente de información que nos dé alguna base de modelo. Hasta podemos armar archivos de modelo (recuerden, el modelo lo deciden uds, dónde va, qué tiene, es todo libre) desde otro modelo. Hace unos dos años, escribí &lt;a href="http://msmvps.com/blogs/lopez/archive/2007/11/25/ajgenesis-modelo-desde-la-base-de-datos.aspx" target="_blank"&gt;sobre generar el modelo desde la base de datos&lt;/a&gt;. En mi opinión, la base de datos no es el modelo más expresivo, pero es uno muy ubicuo: puede servir como punto de partida, y desde la base de datos, generar un modelo que podemos refinar posteriormente.&lt;/p&gt;  &lt;p&gt;(sobre el tema de modelos pueden leer &lt;a href="http://msmvps.com/blogs/lopez/archive/2009/06/29/modelos-y-metamodelos-en-ajgenesis.aspx"&gt;Modelos y metamodelos en AjGenesis&lt;/a&gt;: los metamodelos no son necesarios ni obligatorios, pero es un tema que estoy agregando en el proyecto, como opcional).&lt;/p&gt;  &lt;p&gt;(un tipo de modelo a explorar &lt;a href="http://msmvps.com/blogs/lopez/archive/2008/10/03/otro-modelo-para-ajgenesis.aspx"&gt;Otro modelo para AjGenesis&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;Hoy quiero entonces volver sobre el tema de generar un modelo desde otro modelo, esta vez usando el esquema de la base de datos que tengamos entre manos. Es sólo un ejemplo “prueba de concepto”. Pero en el proyecto ágil en que estoy participando, el equipo tomó la base que ya tenían y generó un modelo usando técnicas como las de este ejemplo, usando AjGenesis, y ahora, ya abandonaron la base inicial, y usan directamente el modelo generado alguna vez y refinado desde entonces.&lt;/p&gt;  &lt;p&gt;Pueden bajar el ejemplo actual de mi Skydrive &lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/AjGenesis/DatabaseExample01.zip" target="_blank"&gt;DatabaseExample01.zip&lt;/a&gt;. (el código está en &lt;a href="http://ajgenesis.codeplex.com/SourceControl/ListDownloadableCommits.aspx" target="_blank"&gt;el repositorio de código en Codeplex&lt;/a&gt;, bajo el directorio examples\DatabaseExamples). El .zip de Skydrive tiene todo lo necesario, incluso la versión en desarrollo de AjGenesis ya compilada.&lt;/p&gt;  &lt;p&gt;Despues de bajarlo y expandirlo, tenemos estas carpetas:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajgenesisdb04.png" alt="" /&gt;&lt;/p&gt;  &lt;p&gt;Hay un solo proyecto de ejemplo. EL contenido de Projects\Northwind\Metadata.xml:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="font-size:12px;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metadata&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Northwind&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Database&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Northwind&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;ConnectionString&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;server=.\SQLEXPRESS;database=Northwind;Integrated Security=true&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;ConnectionString&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Database&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metadata&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Describe el string de conexión a usar para llegar a la base de ejemplo. Estoy usando la Northwind, en SQL Server (pueden usar el full o el express). Si no tienen esa base de datos, los scripts de creación están en el directorio Sql.&lt;/p&gt;

&lt;p&gt;Para generar el proyecto, el modelos con sus entidades, ejecutar:&lt;/p&gt;

&lt;p&gt;&lt;font face="Consolas"&gt;MakeModelFromDatabase.cmd&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;AjGenesis (compilado en el directorio Bin) comienza su trabajo:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajgenesisdb02.png" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;El comando que ejecutamos contiene:&lt;/p&gt;

&lt;p&gt;&lt;font face="Consolas"&gt;Bin\AjGenesis.Console Projects\Northwind\Metadata.xml Tasks\DatabaseProcess.ajg&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Este comando carga el contenido de Metadata.xml como modelo en memoria, y ejecuta la tarea DatabaseProcess.ajg escrita en el lenguaje dinámico que uso AjBasic. Esta tarea usa las vista de &lt;a href="http://msdn.microsoft.com/en-us/library/ms186778.aspx" target="_blank"&gt;Information Schema&lt;/a&gt; para obtener información acerca de la estructura de la base de datos (usando estas vistas, que están definidas en el estándar SQL, y presentes en varias bases de datos, nos abre la puerta para conseguir trabajar con otras marcas que no sean MS SQL Server; debería probar, por ejemplo, con Oracle).&lt;/p&gt;

&lt;p&gt;La tarea crea el archivo Projects\Northwind\Project.xml:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;?&lt;/span&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot; standalone=&amp;quot;yes&amp;quot;&lt;span style="color:#0000ff;"&gt;?&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Northwind&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Customer.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Shipper.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Supplier.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Order.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Product.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/OrderDetail.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/CustomerCustomerDemo.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/CustomerDemographic.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Region.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Territory.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/EmployeeTerritory.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Employee.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;    
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Entities/Category.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;El proyecto y las entidades son parecidas a las que usé en &lt;a href="http://msmvps.com/blogs/lopez/archive/2007/06/25/generando-aplicaciones-con-ajgenesis.aspx" target="_blank"&gt;Generando aplicaciones con AjGenesis&lt;/a&gt; (pero no es igual, estoy experimentando con mejoras). Parte del contenido del archivo generado Projects\Northwind\Entities\Customer.xml nos da una idea de lo que se captura de una “Entity”:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;?&lt;/span&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot; standalone=&amp;quot;yes&amp;quot;&lt;span style="color:#0000ff;"&gt;?&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customer&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customer&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Descriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customer&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Descriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetDescriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetDescriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlCatalog&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Northwind&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlCatalog&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlSchema&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;dbo&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlSchema&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;CustomerID&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;CustomerID&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;CustomerID&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlLength&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;5&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlLength&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IsKey&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;True&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;IsKey&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;nchar&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SystemType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;String&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SystemType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;IsNullable&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;False&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;IsNullable&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
....
  &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;La lógica principal de todo este proceso de generación, reside en la tarea Tasks\DatabaseProcess.ajg, de nuevo escrita en AjBasic (I love this language! :-) un fragmento:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;cmd = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; System.Data.SqlClient.SqlCommand()
cmd.Connection = conn
cmd.CommandText = &amp;quot;&lt;span style="color:#8b0000;"&gt;select * from Information_Schema.Tables where Table_Type = &amp;#39;BASE TABLE&amp;#39;&lt;/span&gt;&amp;quot;
conn.Open()
PrintLine &amp;quot;&lt;span style="color:#8b0000;"&gt;Reader&lt;/span&gt;&amp;quot;
dr = cmd.ExecuteReader()
Tables = CreateList()
&lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; dr.Read()
  PrintLine &amp;quot;&lt;span style="color:#8b0000;"&gt;Table &lt;/span&gt;&amp;quot; &amp;amp; dr.Item(&amp;quot;&lt;span style="color:#8b0000;"&gt;Table_Name&lt;/span&gt;&amp;quot;) &amp;amp; &amp;quot;&lt;span style="color:#8b0000;"&gt;: &lt;/span&gt;&amp;quot; &amp;amp; dr.Item(&amp;quot;&lt;span style="color:#8b0000;"&gt;Table_Type&lt;/span&gt;&amp;quot;)
  Table = CreateObject()
  Table.SqlCatalog = dr.Item(&amp;quot;&lt;span style="color:#8b0000;"&gt;Table_Catalog&lt;/span&gt;&amp;quot;)
  Table.SqlSchema = dr.Item(&amp;quot;&lt;span style="color:#8b0000;"&gt;Table_Schema&lt;/span&gt;&amp;quot;)
  Table.SqlName = dr.Item(&amp;quot;&lt;span style="color:#8b0000;"&gt;Table_Name&lt;/span&gt;&amp;quot;)
  Table.Name = Table.SqlName.Replace(&amp;quot;&lt;span style="color:#8b0000;"&gt; &lt;/span&gt;&amp;quot;,&amp;quot;&lt;span style="color:#8b0000;"&gt;&lt;/span&gt;&amp;quot;)
  
  &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; IsPlural(Table.Name) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
    Table.SetName = Table.Name
    Table.Name = ToSingular(Table.Name)
  &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
    Table.SetName = ToPlural(Table.Name)
  &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
  
  Table.Descriptor = Table.Name
  Table.SetDescriptor = Table.SetName
  
  Table.Description = Table.Name
  
  Tables.Add(Table)
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;while&lt;/span&gt;
dr.Close()&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;Posibles mejoras&lt;/h3&gt;

&lt;p&gt;Como escribí más arriba, este ejemplo es una “prueba de concepto”; una versión anterior la usamos en un proyecto real. Pero hay varios puntos a mejorar:&lt;/p&gt;

&lt;p&gt;- Usar el modelo generado para generar una aplicación que funcione, con scaffolding o no.&lt;/p&gt;

&lt;p&gt;- Soportar más metadata que obtengamos via Information Schema&lt;/p&gt;

&lt;p&gt;- Probar con otras marcas de bases de datos, y con bases de datos reales&lt;/p&gt;

&lt;p&gt;- Tratamiento de relaciones: detectar borrados en cascadas, soportar claves primarias compuestas, otras acciones.&lt;/p&gt;

&lt;p&gt;Otros posts relacionados (aparte de los ya mencionados):&lt;/p&gt;

&lt;h6&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2006/11/19/generando-c-digo-hello-world-con-ajgenesis.aspx"&gt;Generando Código: Hello World con AjGenesis&lt;/a&gt;&lt;/h6&gt;

&lt;h6&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/11/27/ajgenesis-modelo-generado-desde-los-assemblies.aspx"&gt;AjGenesis: Modelo generado desde los assemblies&lt;/a&gt;&lt;/h6&gt;

&lt;h6&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/09/29/modelo-textual-para-generaci-243-n-de-c-243-digo-con-ajgenesis.aspx"&gt;Modelo textual para generación de código con AjGenesis&lt;/a&gt;&lt;/h6&gt;

&lt;p&gt;Si es la primera vez que se topan con generación de código con AjGenesis, &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx" target="_blank"&gt;tengo varios posts escritos&lt;/a&gt;. Recomiendo un video, producido gracias a la comunidad ALT.NET Hispano: &lt;a href="http://msmvps.com/blogs/lopez/archive/2009/10/27/resultado-de-la-van-alt-net-hispano-sobre-generaci-243-n-de-c-243-digo.aspx"&gt;Resultado de la VAN ALT.NET Hispano sobre Generación de Código&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1743328" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Generando código con AjGenesis usando archivos de mapeo de NHibernate</title><link>http://msmvps.com/blogs/lopez/archive/2009/11/23/generating_2D00_code_2D00_with_2D00_ajgenesis_2D00_using_2D00_nhibernate_2D00_hbm_2D00_files.aspx</link><pubDate>Mon, 23 Nov 2009 09:18:30 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1741719</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1741719</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/11/23/generating_2D00_code_2D00_with_2D00_ajgenesis_2D00_using_2D00_nhibernate_2D00_hbm_2D00_files.aspx#comments</comments><description>&lt;p&gt;En estos días, estuve trabajando en generar código de clases C#, usando como punto de partida los archivos .hbm, que se usan en &lt;a href="http://nhforge.org" target="_blank"&gt;NHibernate&lt;/a&gt; para especificar el mapeo de clases y tablas de bases relacionales. Como es usual, cuando encaro algo de generación de código uso &lt;a href="http://ajgenesis.codeplex.com" target="_blank"&gt;AjGenesis&lt;/a&gt;, mi proyecto open source de generación de código (practico el “dog fooding” :-).&lt;/p&gt;  &lt;p&gt;(English version of this post &lt;a href="http://ajlopez.wordpress.com/2009/11/22/generating-code-with-ajgenesis-using-nhibernate-hbm-files/" target="_blank"&gt;Generating code with AjGenesis using NHibernate hbm files&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;Pueden bajar un ejemplo de lo que estoy haciendo de mi Skydrive:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/AjGenesis/NHibernateMappingExample01.zip" target="_blank"&gt;Examples &amp;gt; AjGenesis &amp;gt; NHibernateMappingExample01.zip&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(el código en desarrollo está en el trunk, en &lt;a href="http://ajgenesis.codeplex.com/sourcecontrol/changeset/view/61684?projectName=ajgenesis#" target="_blank"&gt;este change actual&lt;/a&gt;, en el directorio examples\NHibernateMappinp:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesisnh03.png" alt="" /&gt;&lt;/p&gt;  &lt;p&gt;pero si quieren ir directamente al ejemplo, pueden bajárselo completo desde el Skydrive que mencioné, que incluye el ejecutable de AjGenesis de la versión en desarrollo, no necesitan compilar nada).&lt;/p&gt;  &lt;p&gt;Luego de expandir el archivo del ejemplo, tendrán este contenido:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesisnh02.png" alt="" /&gt;&lt;/p&gt;  &lt;p&gt;Para crear clases C#, pueden probar de ejecutar los comandos:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;GenerateClasses AjFirstExample
GenerateClasses AjTest&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Para crear un proyecto .NET con los archivos .cs y .hbm, y una solución, ejecutar:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;GenerateProject AjFirstExample
GenerateProject AjTest&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Los archivos generados, en ambos casos, quedan en el directorio Build.&lt;/p&gt;

&lt;p&gt;Hay dos proyectos ejemplo que son AjFirstExample, con dos mapeos simples, y AjTest, que tiene mapeos más interesantes, con “bags” y relaciones “many to one”.&lt;/p&gt;

&lt;p&gt;En el ejemplo, cada proyecto se describe con un simple archivo Project.xml:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;AjTest&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;En cuanto necesite más información, lo agregaré ahí, o en tags meta de los propios archivos de mapeo y configuración.&lt;/p&gt;

&lt;p&gt;Este es uno de los archivos de mapeo que sirven de modelo inicial para este ejemplo de generación, en Projects\AjTest\Mappings, Department.hbm:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;?&lt;/span&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;span style="color:#0000ff;"&gt;?&amp;gt;&lt;/span&gt; 
&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate&lt;/span&gt;-&lt;span style="color:#ff0000;"&gt;mapping&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;xmlns&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;urn:nhibernate-mapping-2.2&amp;quot;&lt;/span&gt;
  &lt;span style="color:#ff0000;"&gt;assembly&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;AjTest.Entities&amp;quot;&lt;/span&gt;
  &lt;span style="color:#ff0000;"&gt;namespace&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;AjTest.Entities&amp;quot;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
  &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;class&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Department&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;table&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;departments&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;id&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;column&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Int32&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;generator&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;class&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;native&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;id&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Description&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;type&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;String&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;bag&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;name&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;Employees&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;lazy&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;inverse&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;cascade&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;pre style="margin:0px;width:100%;font-size:12px;background-color:#ffffff;"&gt;      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;key&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;column&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;IdDepartment&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;one&lt;/span&gt;-&lt;span style="color:#ff0000;"&gt;to&lt;/span&gt;-&lt;span style="color:#ff0000;"&gt;many&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;class&lt;/span&gt;=&lt;span style="color:#0000ff;"&gt;&amp;quot;AjTest.Entities.Employee, AjTest.Entities&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;bag&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;class&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;hibernate&lt;/span&gt;-mapping&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Este es el código generado para este mapeo, Department.generated.cs:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System;
&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span style="color:#0000ff;"&gt;using&lt;/span&gt; Iesi.Collections.Generic;
&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt; AjTest.Entities 
{
  &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Department {
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; Id { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; Description { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; IList&amp;lt;Employee&amp;gt; Employees { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Department() 
    {
      &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Employees = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List&amp;lt;Employee&amp;gt;();
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Veamos el proceso de generación. Este es el contenido de GenerateProject.cmd:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;@echo off
&lt;span style="color:#0000ff;"&gt;set&lt;/span&gt; ProjectName=%1%
&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;%1%&lt;/span&gt;&amp;quot;==&amp;quot;&lt;span style="color:#8b0000;"&gt;&lt;/span&gt;&amp;quot; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt; ProjectName=AjFirstExample
Bin\AjGenesis.Console.exe Projects\%ProjectName%\Project.xml Tasks\AddMappings.ajg Tasks\BuildCSharp.ajg
xcopy Libraries\*.* Build\%ProjectName%\CSharp\Src\Libraries /Y /Q&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;La línea más importante es la que invoca a AjGenesis.Console.exe. El contenido de Project.xml se carga en memoria. La tarea AddMapping.ajg se carga y ejecuta (está escrita en un lenguaje dinámico, afectuosamente llamado AjBasic), y luego, se procesa la tarea BuildCSharp.ajg. Veamos el código de AddMapping.ajg:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; Add mappings from directory if not specified in Project model&lt;/span&gt;
Include(&amp;quot;&lt;span style="color:#8b0000;"&gt;Utilities/Utilities.tpl&lt;/span&gt;&amp;quot;)
&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; Project.Mappings &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
  Project.Mappings = CreateList()
  
  di = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; System.IO.DirectoryInfo(&amp;quot;&lt;span style="color:#8b0000;"&gt;Projects/${Project.Name}/Mappings&lt;/span&gt;&amp;quot;)
  
  &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; fi &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; di.GetFiles(&amp;quot;&lt;span style="color:#8b0000;"&gt;*.hbm.xml&lt;/span&gt;&amp;quot;)
    filename = fi.Name
    Project.Mappings.Add(filename.Substring(0, filename.Length - 8))
  &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Encuentra y agrega los nombres de los archivos de mapeo contenidos en el directorio de Mapping, dentro del proyecto (noten que se pueden usar clases y objetos del framework .NET). Una tarea más interesante es la GenerateCSharp.ajg. Primero, carga la dll de NHibernate, para usar más adelante su parser de archivos hbm:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;include &amp;quot;&lt;span style="color:#8b0000;"&gt;Utilities/Utilities.tpl&lt;/span&gt;&amp;quot;
include &amp;quot;&lt;span style="color:#8b0000;"&gt;Utilities/FileUtilities.tpl&lt;/span&gt;&amp;quot;
include &amp;quot;&lt;span style="color:#8b0000;"&gt;Utilities/TypeUtilities.tpl&lt;/span&gt;&amp;quot;
Include(&amp;quot;&lt;span style="color:#8b0000;"&gt;Utilities/NHibernateUtilities.tpl&lt;/span&gt;&amp;quot;)
include &amp;quot;&lt;span style="color:#8b0000;"&gt;Templates/CSharp/UtilitiesCs.tpl&lt;/span&gt;&amp;quot;
include &amp;quot;&lt;span style="color:#8b0000;"&gt;Templates/CSharp/CSharpFunctions.tpl&lt;/span&gt;&amp;quot;
AssemblyManager.LoadFrom(&amp;quot;&lt;span style="color:#8b0000;"&gt;Libraries/NHibernate.dll&lt;/span&gt;&amp;quot;)
parser = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; NHibernate.Cfg.MappingSchema.MappingDocumentParser()
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Crea objetos dinámicos, donde coloca información de la solución y el proyecto a crear:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; Project.BuildDir &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
  Project.BuildDir = &amp;quot;&lt;span style="color:#8b0000;"&gt;Build/${Project.Name}/CSharp&lt;/span&gt;&amp;quot;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
message &amp;quot;&lt;span style="color:#8b0000;"&gt;Creating Directories...&lt;/span&gt;&amp;quot;
FileManager.CreateDirectory(Project.BuildDir)
FileManager.CreateDirectory(&amp;quot;&lt;span style="color:#8b0000;"&gt;${Project.BuildDir}/Sql&lt;/span&gt;&amp;quot;)
FileManager.CreateDirectory(&amp;quot;&lt;span style="color:#8b0000;"&gt;${Project.BuildDir}/Src&lt;/span&gt;&amp;quot;)
FileManager.CreateDirectory(&amp;quot;&lt;span style="color:#8b0000;"&gt;${Project.BuildDir}/Src/Libraries&lt;/span&gt;&amp;quot;)
message &amp;quot;&lt;span style="color:#8b0000;"&gt;Defining Solution and Projects...&lt;/span&gt;&amp;quot;
Project.Solution = CreateObject()
Project.Solution.Guid = &amp;quot;&lt;span style="color:#8b0000;"&gt;FAE04EC0-301F-11D3-BF4B-00C04F79EFBC&lt;/span&gt;&amp;quot;
Project.Solution.Projects = CreateList()
message &amp;quot;&lt;span style="color:#8b0000;"&gt;Defining Entities Project...&lt;/span&gt;&amp;quot;
PrjEntities = CreateObject()
PrjEntities.Includes = CreateList()
PrjEntities.Guid = CreateGuid()
PrjEntities.COMGuid = CreateGuid()
Project.Solution.Projects.Add(PrjEntities)
Project.Entities = CreateList()
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Ahora, itera sobre cada archivo hbm, lo lee usando el parser del propio NHibernate, toma información sobre las clases a generar:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; MappingName &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Project.Mappings
  filename = &amp;quot;&lt;span style="color:#8b0000;"&gt;Projects/${Project.Name}/Mappings/${MappingName}.hbm.xml&lt;/span&gt;&amp;quot;
  mapping = parser.Parse(OpenAsStream(filename))
    
  &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; hbmclass &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; mapping.Items where IsType(hbmclass, &amp;quot;&lt;span style="color:#8b0000;"&gt;HbmClass&lt;/span&gt;&amp;quot;)
    Entity = CreateObject()
    
    Project.Entities.Add(Entity)
  
    Entity.ClassName = hbmclass.name
    Entity.&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt; = mapping.&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt;
    
    &lt;span style="color:#008000;"&gt;&amp;#39; Namespace as default project name for Entities Project&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; PrjEntities.Name &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
      PrjEntities.Name = mapping.&lt;span style="color:#0000ff;"&gt;namespace&lt;/span&gt;
      PrjEntities.Directory = &amp;quot;&lt;span style="color:#8b0000;"&gt;${Project.BuildDir}/Src/${PrjEntities.Name}&lt;/span&gt;&amp;quot;
      FileManager.CreateDirectory(PrjEntities.Directory)
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
    
    Entity.Properties = CreateList()
    
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; hbmclass.Id &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; = CreateObject()
      &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Name = hbmclass.Id.name
      &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Type = HbmTypeToCSharp(hbmclass.Id.type1, Entity.&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt;)
      Entity.Properties.Add(&lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;)
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; item &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; hbmclass.Items
      &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; IsType(item, &amp;quot;&lt;span style="color:#8b0000;"&gt;HbmProperty&lt;/span&gt;&amp;quot;) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; = CreateObject()
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Name = item.name
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Type = HbmTypeToCSharp(item.type1, Entity.&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt;)
        Entity.Properties.Add(&lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;)
      &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
      
      &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; IsType(item, &amp;quot;&lt;span style="color:#8b0000;"&gt;HbmManyToOne&lt;/span&gt;&amp;quot;) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; = CreateObject()
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Name = item.name
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Type = HbmTypeToCSharp(item.&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, Entity.&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt;)
        Entity.Properties.Add(&lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;)
      &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; IsType(item, &amp;quot;&lt;span style="color:#8b0000;"&gt;HbmSet&lt;/span&gt;&amp;quot;) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; = CreateObject()
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Name = item.name
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.IsSet = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Type = HbmTypeToCSharp(item.Item.&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, Entity.&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt;)
        Entity.Properties.Add(&lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;)
      &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
      &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; IsType(item, &amp;quot;&lt;span style="color:#8b0000;"&gt;HbmBag&lt;/span&gt;&amp;quot;) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt; = CreateObject()
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Name = item.name
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.IsList = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;.Type = HbmTypeToCSharp(item.Item.&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;, Entity.&lt;span style="color:#0000ff;"&gt;Namespace&lt;/span&gt;)
        Entity.Properties.Add(&lt;span style="color:#0000ff;"&gt;Property&lt;/span&gt;)
      &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;    
  &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Pueden extender esta capacidades, procesando más tags (debería escribir un ejemplo usando los tags meta que puede contener el hbm; ya utilitarios de Java, como el venerable XDocLet, usaban esos tags para ayudarse en la generación de código, en Hibernate), y detectar más formas de mapeo de NHibernate. Ahora, pasa a la generación de código:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; Entity &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Project.Entities
  TransformerManager.Transform(&amp;quot;&lt;span style="color:#8b0000;"&gt;Templates/CSharp/Entity.tpl&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;${PrjEntities.Directory}/${Entity.ClassName}.generated.cs&lt;/span&gt;&amp;quot;, Environment)
  PrjEntities.Includes.Add(CreateFileCs(&amp;quot;&lt;span style="color:#8b0000;"&gt;${Entity.ClassName}.generated&lt;/span&gt;&amp;quot;))
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;La tarea genera los archivos .cs, y también crea un archivo de solución y otro de proyecto C#, copiando y embebiendo los archivos de mapeo originales:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:10pt;margin:0px;width:100%;font-family:consolas;background-color:#ffffff;"&gt;&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; MappingName &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Project.Mappings
  filename = &amp;quot;&lt;span style="color:#8b0000;"&gt;Projects/${Project.Name}/Mappings/${MappingName}.hbm.xml&lt;/span&gt;&amp;quot;
  targetfilename = &amp;quot;&lt;span style="color:#8b0000;"&gt;${PrjEntities.Directory}/${MappingName}.hbm.xml&lt;/span&gt;&amp;quot;
  System.IO.File.Copy(filename, targetfilename, &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;)
  PrjEntities.Includes.Add(CreateFileType(MappingName,&amp;quot;&lt;span style="color:#8b0000;"&gt;hbm.xml&lt;/span&gt;&amp;quot;))
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;each&lt;/span&gt; CsProject &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Project.Solution.Projects where CsProject.ProjectType&amp;lt;&amp;gt;&amp;quot;&lt;span style="color:#8b0000;"&gt;Web&lt;/span&gt;&amp;quot;
  FileManager.CreateDirectory(CsProject.Directory)
  FileManager.CreateDirectory(CsProject.Directory &amp;amp; &amp;quot;&lt;span style="color:#8b0000;"&gt;/Properties&lt;/span&gt;&amp;quot;)
  TransformerManager.Transform(&amp;quot;&lt;span style="color:#8b0000;"&gt;Templates/CSharp/CsProject.tpl&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;${CsProject.Directory}/${CsProject.Name}.csproj&lt;/span&gt;&amp;quot;, Environment)
  TransformerManager.Transform(&amp;quot;&lt;span style="color:#8b0000;"&gt;Templates/CSharp/AssemblyInfoCs.tpl&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;${CsProject.Directory}/Properties/AssemblyInfo.cs&lt;/span&gt;&amp;quot;, Environment)
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;for&lt;/span&gt;
TransformerManager.Transform(&amp;quot;&lt;span style="color:#8b0000;"&gt;Templates/Solution.tpl&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;${Project.BuildDir}/Src/${Project.Name}.sln&lt;/span&gt;&amp;quot;, Environment)
&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Esta es la solución generada:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesisnh01.png" alt="" /&gt;&lt;/p&gt;

&lt;h3&gt;Próximos pasos&lt;/h3&gt;

&lt;p&gt;Debería trabajar en algunos puntos:&lt;/p&gt;

&lt;p&gt;- Generar una solución más completa, como en otros ejemplos de AjGenesis (con un proyecto de infraestructura, un proyecto de Service Layer o similar, una presentación web, etc…).&lt;/p&gt;

&lt;p&gt;- Soportar más opciones de mapeo de NHibernate.&lt;/p&gt;

&lt;p&gt;- Usar los tags meta.&lt;/p&gt;

&lt;p&gt;Por ahora, pueden jugar con este ejemplo. Pueden cambiar los templates para generar más artefactos, por ejemplo, código VB.NET.&lt;/p&gt;

&lt;p&gt;Gracias a &lt;a href="http://twitter.com/fabiomaulo" target="_blank"&gt;@fabiomaulo&lt;/a&gt; por avisarmr de las capacidades públicas de parser de hbm dentro de NHibernate!&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1741719" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/NHibernate/default.aspx">NHibernate</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Resultado de la VAN ALT.NET Hispano sobre Generación de Código</title><link>http://msmvps.com/blogs/lopez/archive/2009/10/27/resultado-de-la-van-alt-net-hispano-sobre-generaci-243-n-de-c-243-digo.aspx</link><pubDate>Tue, 27 Oct 2009 16:15:40 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1735639</guid><dc:creator>lopez</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1735639</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/10/27/resultado-de-la-van-alt-net-hispano-sobre-generaci-243-n-de-c-243-digo.aspx#comments</comments><description>&lt;p&gt;&lt;img style="display:inline;margin:0px 20px 20px 0px;" src="http://www.todocontenidos.com/images/articles/gencodvan01.png" align="left" alt="" /&gt; Gracias a la comunidad ALT.NET Hispano, quedó publicado el video de la VAN (des-conferencia virtual) sobre Generación de Código, al que fui invitado. Ahí presenté mi proyecto personal preferido, &lt;a href="http://ajgenesis.codeplex.com/" target="_blank"&gt;AjGenesis&lt;/a&gt;, generador de código, escrito en .NET, y publicado en código abierto. Pueden ver el resultado en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://altnet-hispano.pbworks.com/van-2009-09-26-generacion-codigo" target="_blank"&gt;VAN – Septiembre 26 de 2009 – Generación de Código&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ahí encontraran el video, enlaces, lecturas, y la presentación que utilicé, para descargar.&lt;/p&gt;  &lt;p&gt;Al final de mi presentación, hubo discusión y preguntas. Uno de los puntos mencionados, fue cuales serán los próximos pasos de AjGenesis. Algo comenté ahí, pero me gustaría contestar algo más en detalle por acá:&lt;/p&gt;  &lt;p&gt;- En principio, es un proyecto que me gusta, y que me ha resultado muy flexible. Y al que voy a seguir incorporando características.&lt;/p&gt;  &lt;p&gt;- Hay desarrolladores que lo usan, pero son pocos, o por lo menos, no publican resultados, o escriben posts (en estos últimos 5 años, debe haber 4 post sobre AjGenesis NO escritos por mí, solamente; tampoco es mencionado mucho en las listas de correo, sobre desarrollo de software en general, que frecuento (debe haber dos o tres menciones en los últimos 3 años)). Entonces, como digo en la des-conferencia, “lo uso yo y mi tía Carlota”… :-)&lt;/p&gt;  &lt;p&gt;- Hay que mejorar la documentación. Por ahora, estoy escribiendo &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx" target="_blank"&gt;posts casi todos los meses sobre el tema&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;- Lo que me gustaría encarar, es poner en línea el tema de &lt;a href="http://msmvps.com/blogs/lopez/archive/2008/04/03/code-generation-as-a-service.aspx" target="_blank"&gt;Code Generation as a Service&lt;/a&gt;, que menciono en la charla.&lt;/p&gt;  &lt;p&gt;Como comento hacia el final de la presentación, cuando expongo sobre generación de código, lo hago mostrando ideas e implementaciones con AjGenesis, porque me siento más cómodo. Pero, por supuesto, hay multitud de otras herramientas, más documentadas, con más soporte, con más comunidad, que pueden usar. La idea de la presentación es que tengan contacto con lo pragmático de generar código, y que vaya quedando en claro por qué estamos hoy generando código: ante la multitud de tecnologías, frameworks y librerías, es un poco difícil zafar de escribir y escribir código. Y como las tecnologías, frameworks y librerías son buenas, en general, es difícil también, hoy por hoy, prescindir de ellas. He dejado enlaces a otras herramientas en la página de la VAN.&lt;/p&gt;  &lt;p&gt;Otro camino a explorar sería abandonar todo eso, y buscar la simplicidad. Algo expongo en &lt;a href="http://msmvps.com/blogs/lopez/archive/2009/10/16/191-es-tiempo-de-volver-a-la-simplicidad.aspx" target="_blank"&gt;¿Es tiempo de volver a la simplicidad?&lt;/a&gt;. Pero, yendo a la realidad, de todos los días, eso todavía no está, y quien sabe cuándo volveremos o conseguiremos eso. Así, que caemos de nuevo en tecnología, frameworks y librerías.&lt;/p&gt;  &lt;p&gt;Como expongo en el post citado, otro camino, que algunos&amp;#160; de Uds. habrán recorrido, habrá sido armarse su propio framework y librerías. Ante la calidad y cantidad de librerías disponibles, y todas las necesidades a cubrir, es un camino algo difícil de recorrer actualmente. Y aún recorrido ese camino, muchas veces nuestro framework necesita que trabajemos incorporando código o archivos de configuración, que bien podemos generar automáticamente desde un modelo.&lt;/p&gt;  &lt;p&gt;Si es la primera vez que visitan este blog, y quieren conocer por qué le dedico tanto tiempo a la generación de código, y encontrar una explicación más detallada de lo que planteo en la charla y en los párrafos de arriba, les recomiendo leer primero mi post &lt;a href="http://msmvps.com/blogs/lopez/archive/2007/08/02/sobre-la-generaci-243-n-de-c-243-digo.aspx" target="_blank"&gt;Sobre la generación de código&lt;/a&gt;. Más enlaces, más relacionados con AjGenesis, en &lt;a href="http://msmvps.com/blogs/lopez/archive/2008/06/10/quot-ver-la-luz-quot-con-generaci-243-n-de-c-243-digo-y-ajgenesis.aspx" target="_blank"&gt;Ver la luz con generación de código y AjGenesis&lt;/a&gt; :-)&lt;/p&gt;  &lt;p&gt;Como verán en el video, y en algunos enlaces que están en la página de la VAN, y leen &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx" target="_blank"&gt;los posts anteriores sobre generación de código y AjGenesis&lt;/a&gt; que ya he escrito, la idea no es solamente generar código, sino generar código desde un modelo: llevamos años eludiendo modelos, solamente dibujándolos (en UML, por ejemplo), pero sin utilizarlos como instrumentos para implementar efectivamente un sistema. La conversión de un modelo a código concreto, ha quedado en nuestras manos. Y ante la cantidad del trabajo, es hora de “elevar el nivel de abstracción”, y comenzar a basarnos en modelos. De alguna forma, eso es lo que hicimos cuando pasamos de programar en lenguaje de máquina, a ensamblador, y luego, a lenguajes de programación: nos olvidamos de los detalles, y le dejamos ese trabajo a la propia máquina. Estamos generando código cada día: ya no armamos el .exe a mano (como en los tiempos de la ENIAC), sino que hay herramientas (compilador ¿recuerdan?) que pasa nuestro modelo (el programa escrito en un lenguaje de modelado de instrucciones, llamado lenguaje de programación) a código ejecutable (instrucciones para nuestros procesadores).&lt;/p&gt;  &lt;p&gt;El tema es que desde hace años, nos hemos quedado en ese nivel de abstracción. Menciono en la charla, que hubo excepciones: hubo algunos avances y adoptamos modelos para olvidarnos de los detalles, en algunos casos. Un caso que menciono: Visual Basic (el clásico, de los noventa). Cuando apareció Visual Basic, ya no hubo que programar ventanas, botones y eventos de Windows, en C, ocupando decenas de líneas para hacer un simple “Hola, mundo” (era lo que yo llamo la “Era Petzoldiana”). Ahora, con un modelo gráfico, arrastramos botones, cajas de textos, y voilá: tenemos el código de un formulario (vean que en .NET, tanto en VB.NET como en C#, todavía es más evidente que generamos código: el diseñador genera el código correspondiente a crear los controles, ponerles las propiedades, por nuestra cuenta y orden).&lt;/p&gt;  &lt;p&gt;Bueno, basta por ahora. Pasen y vean el video, vean las discusiones, y participen de la comunidad ALT.NET Hispano.&lt;/p&gt;  &lt;p&gt;Si les interesa el tema de la generación de código, hay una lista de correo, sobre el tema, en español. Pueden ver los mensajes y suscribirse, en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://groups.google.com/group/codegeneration"&gt;http://groups.google.com/group/codegeneration&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1735639" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Video/default.aspx">Video</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ALT.NET/default.aspx">ALT.NET</category></item><item><title>La generación de código y el trabajo de desarrollo de software</title><link>http://msmvps.com/blogs/lopez/archive/2009/07/22/la-generaci-243-n-de-c-243-digo-y-el-trabajo-de-desarrollo-de-software.aspx</link><pubDate>Wed, 22 Jul 2009 14:04:06 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1705177</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1705177</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/07/22/la-generaci-243-n-de-c-243-digo-y-el-trabajo-de-desarrollo-de-software.aspx#comments</comments><description>&lt;p&gt;Antes de ayer, 20 de Julio, &lt;a href="http://twitter.com/hallo" target="_blank"&gt;@hallo&lt;/a&gt; twittereaba:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/cgjob01.png" alt="" /&gt;&lt;/p&gt;  &lt;p&gt;Recibió varias respuestas, acá va una mía y otra que recibió:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/cgjob02.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Lo que pasa es que hemos estado generando código por décadas. La herramientas que usamos para eso tiene nombre: compilador. Recuerdan los viejos días? Había que setear los relés en la ENIAC, o usar el panel frontal de la micro Altair para inicializar su memoria. Los compiladores acudieron en nuestra ayuda, generando código desde un modelo de más alto nivel: el lenguaje de programación.&lt;/p&gt;  &lt;p&gt;Pero por las últimas tres décadas, no elevamos el nivel de abstracción: seguimos usando lenguajes de programación directamente, para programa. Algunas excepciones: el lenguaje SQL, que nos relevó de recorrer cursores o buscar en índices ISAM, o el diseñador de formularios de Visual Basic, que nos liberó de escribir decenas de páginas de código de Windows a la Petzold.&lt;/p&gt;  &lt;p&gt;El generar código desde un modelo (como trato de promover desde mi proyecto personal &lt;a href="http://ajgenesis.codeplex.com" target="_blank"&gt;AjGenesis&lt;/a&gt;), es la manera de obtener y usar un nuevo “lenguaje”: sea un DSL, domain specific language, o un DSM, domain specific model, o lo que querramos usar como punto de partida.&lt;/p&gt;  &lt;p&gt;Hoy mismo tenemos demasiadas tecnologías, con miríadas de detalles y configuraciones a atender. Pienso en Spring Framework, Hibernate, Struts 2, JavaServer Faces, ASP.NET MVC, Web Services, Windows Communication Foundation, etc… Sabemos más cosas hoy de cómo desarrollar software, pero las aplicaciones actuales están infectadas de toneladas de detalles técnicos, fruto de problemas y errores. Muchos de esos detalles podrían ser derivados desde un modelo, como en mostrado en ejemplos de AjGenesis que he posteado por acá en los últimos años, creando salidas para diferentes tecnologías.&lt;/p&gt;  &lt;p&gt;Si lo miran bien, esto es lo mismo que decir: “a=fact(4)” es el modelo, y registros de procesador, manipulación de pila, reserva y liberación de memoria, son los detalles que nos resuelve un compilador.´&lt;/p&gt;  &lt;p&gt;Más respuestas en Twitter:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/cgjob03.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Sí, la manipulación de registros de procesador puede ser interesante la primera vez que la aprendemos, pero después de horas y horas de trabajo, y con fechas de entrega para mañana, puede volverse no sólo aburrida, sino también problemática. Es por eso que hubo motivación para crear assemblers, macro assemblers, lenguajes de alto nivel y compiladores para los mismos.&lt;/p&gt;  &lt;p&gt;En mi tweet de arriba, mencion la inteligencia artificial. Bien, debo admitir que es sólo una idea, pero pienso que la generación de código es un campo apropiado para la inteligencia artificial aplicada, que es un término demasiado amplio hoy en día. Daría para otro post en detalle.&lt;/p&gt;  &lt;p&gt;Otra pregunta:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/cgjob04.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Bien, es difícil que en corto y mediano plazo consigamos generar todo desde un modelo. Lo que más afecta: hay muchas tecnologías y cada año aparece un nuevo muchacho en elbarrio (Scala, Clojure, Rest, Cloud Computing, Sharding, aplicaciones móviles… etc…). Entonces, no hay una sola forma de generar software, siempre habrá trabajo para estudiar y aplicar nuevas tecnologías. Pero veo que en cada una de esas tecnologías, hay lugar para aplicar la generación de código, y si partimos de un modelo de alto nivel, el pasaje de una tecnología a otra debe ser menos traumático.&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/cgjob05.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Estoy de acuerdo. Pero déjenme soñar: aplicaciones creando aplicaciones… No podríamos generar en el futuro ese tipo de aplicaciones? … Por lo menos para cuando lleguemos a la Enterprise de Star Trek :-)&lt;/p&gt;  &lt;p&gt;Generanción de código: sky is the limit (es la frase directrix de AjGenesis… :-)&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez    &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1705177" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Enlaces y noticias IV</title><link>http://msmvps.com/blogs/lopez/archive/2009/07/19/enlaces-y-noticias-iv.aspx</link><pubDate>Sun, 19 Jul 2009 13:51:36 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1703061</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1703061</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/07/19/enlaces-y-noticias-iv.aspx#comments</comments><description>&lt;p&gt;Sigo con la costumbre coleccionar enlaces, de distintos temas. Los que me llamaron la atención:&lt;/p&gt;  &lt;h3&gt;PHP&lt;/h3&gt;  &lt;p&gt;Es el lenguaje más usado para el desarrollo de sitios dinámicos en la web. Tiene la simplicidad necesaria, y también el soporte de clases, librerías, acceso a base de datos como para hacerlo más poderoso. Tal vez se ha quedado en el desarrollo web, perdiendo en el terreno de programas de consola, servicios, o de ventanas. Hay montañas de código de ejemplo para estudiar y aprender. Algunos enlaces:&lt;/p&gt;  &lt;p&gt;&lt;a title="PHP programming tips and tricks Code Purity" href="http://blog.code-purity.com/archives/2009/7/14/php_programming_tips_and_tricks/"&gt;PHP programming tips and tricks Code Purity&lt;/a&gt;    &lt;br /&gt;&lt;a title="Scripts Directory of PHP, ASP, ASP.NET, Java, Javascript, Perl and more! - Scripts" href="http://www.scripts.com/"&gt;Scripts Directory of PHP, ASP, ASP.NET, Java, Javascript, Perl and more! – Scripts&lt;/a&gt;    &lt;br /&gt;&lt;a title="43 Must Read PHP Articles and Resources Hi, I&amp;#39;m Grace Smith" href="http://www.gracesmith.co.uk/43-must-read-php-articles-and-resources/"&gt;43 Must Read PHP Articles and Resources Hi, I&amp;#39;m Grace Smith&lt;/a&gt;    &lt;br /&gt;&lt;a title="How To Create Your Own Stats Program (JavaScript, AJAX, PHP) Noupe" href="http://www.noupe.com/php/how-to-create-your-own-stats.html"&gt;How To Create Your Own Stats Program (JavaScript, AJAX, PHP) Noupe&lt;/a&gt;    &lt;br /&gt;&lt;a title="25 Resources to Get You Started with PHP from Scratch - Nettuts+" href="http://net.tutsplus.com/articles/web-roundups/25-resources-to-get-you-started-with-php-from-scratch/"&gt;25 Resources to Get You Started with PHP from Scratch - Nettuts+&lt;/a&gt;    &lt;br /&gt;&lt;a title="15 Wonderfully Creative Uses for PHP" href="http://net.tutsplus.com/tutorials/php/15-wonderfully-creative-uses-for-php/"&gt;15 Wonderfully Creative Uses for PHP&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hay cantidad de sitios manejadores de contenidos (CMS) pueden ver&lt;/p&gt;  &lt;p&gt;&lt;a title="10 New PHP Content Management Systems(CMS)" href="http://www.dreamcss.com/2009/07/10-new-php-content-management.html"&gt;10 New PHP Content Management Systems(CMS)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="http://php.opensourcecms.com/" href="http://php.opensourcecms.com/"&gt;http://php.opensourcecms.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para un rápido Altas, bajas y modicaciones ver &lt;a href="http://www.ajaxcrud.com/" target="_blank"&gt;AjaxCRUD.com - Use PHP &amp;amp; AJAX to CRUD from a mysql database (create / read / update / delete)&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;No creo que alguien pueda pasar fácilmente de PHP a ASP.NET pero pueden leer &lt;a title="Move from PHP to ASP.NET" href="http://msdn.microsoft.com/en-us/rampup/dd861537.aspx"&gt;Move from PHP to ASP.NET&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Tiene sus años, pero es interesante &lt;a title="Understanding MVC in PHP - O&amp;#39;Reilly Media" href="http://www.oreillynet.com/pub/a/php/2005/09/15/mvc_intro.html"&gt;Understanding MVC in PHP - O&amp;#39;Reilly Media&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Un armador de proyectos, a la Apache Ant, pero en PHP: &lt;a title="Phing" href="http://phing.info/trac/"&gt;Phing&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Comenzando con Joomla &lt;a title="Beginners - Joomla! Documentation" href="http://docs.joomla.org/Beginners"&gt;Beginners - Joomla! Documentation&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Veo implementando el &lt;a href="http://en.wikipedia.org/wiki/Template_Attribute_Language" target="_blank"&gt;Template Attribute Language&lt;/a&gt; en PHP: &lt;a title="http://phptal.org/" href="http://phptal.org/"&gt;http://phptal.org/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;DEBEN VER &lt;a href="http://phpcamp.net/index.php" target="_blank"&gt;PHPCamp: learn something new everyday&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para perderse en enlaces, &lt;a href="http://delicious.com/ajlopez/php"&gt;http://delicious.com/ajlopez/php&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;.NET&lt;/h3&gt;  &lt;p&gt;Para los que quieren ver manejadores de contenido (CMS) en ASP.NET:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://aspx.opensourcecms.com/" href="http://aspx.opensourcecms.com/"&gt;http://aspx.opensourcecms.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;El área de código abierto de .NET está bien activo: &lt;a title="Open Source .NET projects" href="http://spreadsheets.google.com/pub?key=pKxDW35algYebfs8nssTjIQ"&gt;Open Source .NET projects&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para estudiar: &lt;a title="Expert to Expert- Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx) Going" href="http://channel9.msdn.com/shows/Going+Deep/Expert-to-Expert-Brian-Beckman-and-Erik-Meijer-Inside-the-NET-Reactive-Framework-Rx/"&gt;Expert to Expert- Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx) Going&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Un ejemplo de referencia &lt;a title="FabrikamShipping - Home" href="http://code.msdn.microsoft.com/FabrikamShipping"&gt;FabrikamShipping – Home&lt;/a&gt; con Geneva Framework, autenticación federada y tutti li fiocci.&lt;/p&gt;  &lt;p&gt;Un camino a explorar: reemplazar ORM (Object Relational Mapping) en runtime por generación de código: &lt;a title=".NET ORM, Object Relational Mapping for .NET Telerik" href="http://www.telerik.com/products/orm.aspx"&gt;.NET ORM, Object Relational Mapping for .NET Telerik&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Librería para Twitter &lt;a title="http://tweetsharp.com/" href="http://tweetsharp.com/"&gt;http://tweetsharp.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;ASP.NET MVC 1.0 ejecutando en Mono &lt;a title="shaml-architecture - Google Code" href="http://code.google.com/p/shaml-architecture/"&gt;shaml-architecture - Google Code&lt;/a&gt; Basado en &lt;a title="s#arp-architecture" href="http://code.google.com/p/sharp-architecture/"&gt;s#arp-architecture&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para mapear objetos &lt;a title="http://automapper.codeplex.com/" href="http://automapper.codeplex.com/"&gt;http://automapper.codeplex.com/&lt;/a&gt; (menos para el bueno de &lt;a href="http://weblogs.shockbyte.com.ar/rodolfof" target="_blank"&gt;Rodolfo Finochietti&lt;/a&gt; que prefiere hacerse su propio mapeador :-)&lt;/p&gt;  &lt;p&gt;Siempre es molesto el DataBinding a propiedades simples, habría que ver qué tal funciona &lt;a title="http://www.codeproject.com/KB/cs/ObjectBindingSource.aspx" href="http://www.codeproject.com/KB/cs/ObjectBindingSource.aspx"&gt;http://www.codeproject.com/KB/cs/ObjectBindingSource.aspx&lt;/a&gt; (nested property binding)&lt;/p&gt;  &lt;p&gt;Más de todo esto en &lt;a href="http://delicious.com/ajlopez/dotnet"&gt;http://delicious.com/ajlopez/dotnet&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Generación de código&lt;/h3&gt;  &lt;p&gt;El proyecto Sculpture está muy bien armado, aunque focalizado en .NET &lt;a title="http://sculpture.codeplex.com/" href="http://sculpture.codeplex.com/"&gt;http://sculpture.codeplex.com/&lt;/a&gt; Es open source, se trasladó a la empresa:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.dawliasoft.com/" href="http://www.dawliasoft.com/"&gt;http://www.dawliasoft.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Tienen una implementación de referencia: &lt;a title="VotingManager.zip" href="http://www.dawliasoft.com/Portals/0/Learn/VotingManager.zip"&gt;VotingManager.zip&lt;/a&gt; que partiendo de 55 líneas, consiguen generar una aplicación de 4111 líneas. Bueno, nada que el &lt;a href="http://ajgenesis.codeplex.com" target="_blank"&gt;AjGenesis&lt;/a&gt; no pueda hacer… :-) … pero es más bonito.&lt;/p&gt;  &lt;p&gt;&lt;a title="Hibernate Class Generation Using hbm2java - O&amp;#39;Reilly Media" href="http://onjava.com/pub/a/onjava/2005/12/14/hibernate-class-generation-with-hbm2java.html?page=last"&gt;Hibernate Class Generation Using hbm2java - O&amp;#39;Reilly Media&lt;/a&gt; Estoy reviendo esto, quiero comenzar a usar el tag &amp;lt;meta&amp;gt; para usar hibernate.cfg.xml y archivos .hbm.xml para alimentar como modelo a &lt;a href="http://ajgenesis.codeplex.com" target="_blank"&gt;AjGenesis&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Para estudiar dos “approachs” &lt;a title="Angle Bracket Percent - CodeDom vs T4- two approaches to Code Generation" href="http://blogs.msdn.com/davidebb/archive/2009/06/03/codedom-vs-t4-two-approaches-to-code-generation.aspx"&gt;Angle Bracket Percent - CodeDom vs T4- two approaches to Code Generation&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Veo el editor de T4 &lt;a title="T4 Editor - tangible T4 Editor plus UML tools" href="http://t4-editor.tangible-engineering.com/T4-Editor-Visual-T4-Editing.html"&gt;T4 Editor - tangible T4 Editor plus UML tools&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Desde AjGenesis puedo leer el archivo .dbml de Linq2Sql, que se puede generar desde la línea de comando con SqlMetal, tengo que estudiar &lt;a title="Oleg Sych - » T4 Toolbox- LINQ to SQL classes generator" href="http://www.olegsych.com/2009/01/t4-toolbox-linq-to-sql-classes-generator/"&gt;Oleg Sych - » T4 Toolbox- LINQ to SQL classes generator&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Yo tenía esta idea, pero la deseché por ser algo “convoluted”, pero es interesante: &lt;a title="Using ASP.Net for Code Generation" href="http://www.delphicsage.com/home/blog.aspx?d=600&amp;amp;title=Using_ASPNet_for_Code_Generation"&gt;Using ASP.Net for Code Generation&lt;/a&gt; . En su tiempo, usé también PHP como lenguaje de generación, pero me gustó tener un lenguaje dedicado a generación con objetos dinámicos (AjBasic) con acceso a un framework de base (.NET por ahora), cosa que no tiene PHP en principio. Y en cuanto a usar ASP.NET, me obligaba a usar un lenguaje tipado .NET, que me resistía a hacerlo.&lt;/p&gt;  &lt;p&gt;Siguiendo con T4, el lenguaje de templates de Visual Studio, a estudiar &lt;a title="Angle Bracket Percent - The MVC T4 template is now up on CodePlex, and it does change your code" href="http://blogs.msdn.com/davidebb/archive/2009/06/26/the-mvc-t4-template-is-now-up-on-codeplex-and-it-does-change-your-code-a-bit.aspx"&gt;Angle Bracket Percent - The MVC T4 template is now up on CodePlex, and it does change your code&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Parece interesante &lt;a title="Sample Fluent NHibernate T4 Templates for Code Generation via LINQ To SQL" href="http://www.pnpguidance.net/Post/SampleFluentNHibernateT4TemplatesCodeGenerationLINQToSQL.aspx"&gt;Sample Fluent NHibernate T4 Templates for Code Generation via LINQ To SQL&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.metacase.com/blogs/stevek/blogView" target="_blank"&gt;Steven Kelly&lt;/a&gt; siempre tiene algo interesante sobre DSM (Domain Specific Models) y generación de código. Comenta sobre &lt;a href="http://www.codegeneration.net/cg2009/" target="_blank"&gt;Code Generation 2009&lt;/a&gt; en &lt;a title="Code Generation 2009 round-up" href="http://www.metacase.com/blogs/stevek/blogView?showComments=true&amp;amp;entry=3423259520"&gt;Code Generation 2009 round-up&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para los que estén con el framework .NET de Lohtka, CSLA, pueden visitar el&lt;/p&gt;  &lt;p&gt;&lt;a title="CslaGenerator Google Groups" href="http://groups.google.com/group/CslaGenerator"&gt;CslaGenerator Google Groups&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ruby es un lenguaje que se presta a la generación de código, ver esto, de hace algunos años, pero a cargo del bueno Jack Herrington, autor de Code Generation in Action (alguien que vió la luz!!! :-) :&lt;/p&gt;  &lt;p&gt;   &lt;div class="wlWriterEditableSmartContent" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:e1c89a3c-3fa7-4139-a58a-282866a26e43" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/p&gt;  &lt;p&gt;Como siempre, más información en &lt;a href="http://delicious.com/ajlopez/codegeneration"&gt;http://delicious.com/ajlopez/codegeneration&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Lenguajes de Programación&lt;/h3&gt;  &lt;p&gt;Descubriendo un clásico: &lt;a title="Let&amp;#39;s Build a Compiler" href="http://compilers.iecc.com/crenshaw/"&gt;Let&amp;#39;s Build a Compiler&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Un texto corto &lt;a href="http://forums.devshed.com/other-programming-languages-139/how-does-an-interpreter-compiler-work-312483.html" target="_blank"&gt;How does a an interpreter compiler work&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para estudiar &lt;a title="Create a Language Compiler for the .NET Framework Using C#" href="http://msdn.microsoft.com/en-us/magazine/cc136756.aspx"&gt;Create a Language Compiler for the .NET Framework Using C#&lt;/a&gt; usa Reflection.Emit, bien a lo macho… :-)&lt;/p&gt;  &lt;p&gt;Hay que escribir intérpretes y compiladores, “compiler generators are for sissies” :-), pero si quieren, pueden ver &lt;a href="http://www.ssw.uni-linz.ac.at/coco/" target="_blank"&gt;The Compiler Generator Coco/R&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Más para ver &lt;a title="Free Compiler Construction Tools- Lexers, Parser Generators, Optimizers (thefreecountry.com)" href="http://www.thefreecountry.com/programming/compilerconstruction.shtml"&gt;Free Compiler Construction Tools- Lexers, Parser Generators, Optimizers (thefreecountry.com)&lt;/a&gt; y &lt;a title="Basics of Compiler Design (pdf)" href="http://www.diku.dk/hjemmesider/ansatte/torbenm/Basics/basics_lulu.pdf"&gt;Basics of Compiler Design (pdf)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para estudiar:&lt;/p&gt;  &lt;p&gt;&lt;a title="Michael Feathers on Programming Languages" href="http://www.infoq.com/interviews/michael-feathers-programming-languages"&gt;Michael Feathers on Programming Languages&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="Synrc Io Language CLR" href="http://synrc.com/io-language.htm"&gt;Synrc Io Language CLR&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="Io (programming language) - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/Io_(programming_language)"&gt;Io (programming language) - Wikipedia, the free encyclopedia&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="InfoQ- The Ioke JVM Language- The power of Lisp and Ruby with an intuitive syntax" href="http://www.infoq.com/news/2008/11/ioke"&gt;InfoQ- The Ioke JVM Language- The power of Lisp and Ruby with an intuitive syntax&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="Ending the Era of Patronizing Language Design" href="http://blog.objectmentor.com/articles/2009/07/13/ending-the-era-of-patronizing-language-design"&gt;Ending the Era of Patronizing Language Design&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Un volver a vivir:&lt;/p&gt;  &lt;p&gt;&lt;a title="History of the BASIC family of languages" href="http://dotnetmasters.com/HistoryOfBasic.htm"&gt;History of the BASIC family of languages&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Otro para el canal “Volver”, entorno de desarrollo xBase:&lt;/p&gt;  &lt;p&gt;&lt;a title="Xailer - El entorno de desarrollo definitivo en xbase" href="http://www.xailer.com/"&gt;Xailer - El entorno de desarrollo definitivo en xbase&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a title="Free Pascal compilers and Pascal Programming - Freebyte&amp;#39;s Guide to" href="http://www.freebyte.com/programming/pascal/"&gt;Free Pascal compilers and Pascal Programming - Freebyte&amp;#39;s Guide to&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Se acuerdan de MUMPS? &lt;a title="MUMPS - Wikipedia, the free encyclopedia" href="http://en.wikipedia.org/wiki/MUMPS"&gt;MUMPS - Wikipedia, the free encyclopedia&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para leer &lt;a title="APL, COBOL, &amp;amp; Dijkstra Paul Murphy ZDNet.com" href="http://blogs.zdnet.com/Murphy/?p=568"&gt;APL, COBOL, &amp;amp; Dijkstra Paul Murphy ZDNet.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Podría volver a estudiar: &lt;a title="COBOL Programming Course" href="http://www.csis.ul.ie/cobol/Course/Default.htm"&gt;COBOL Programming Course&lt;/a&gt;, &lt;a title="The COBOL Programming Language" href="http://www.engin.umd.umich.edu/CIS/course.des/cis400/cobol/cobol.html"&gt;The COBOL Programming Language&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Lista para buscar recursos &lt;a title="Free Programming Tools, free compilers, free software components and" href="http://www.freebyte.com/programming/"&gt;Free Programming Tools, free compilers, free software components and&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Excelente contenido &lt;a title="Google Code University Programming Languages" href="http://code.google.com/intl/it-IT/edu/languages/index.html"&gt;Google Code University Programming Languages&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hay que ir viendo:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://clojure.org/" target="_blank"&gt;Clojure&lt;/a&gt; ver &lt;a title="InfoQ- Rich Hickey on Clojure&amp;#39;s Features and Implementation" href="http://www.infoq.com/interviews/hickey-clojure"&gt;InfoQ- Rich Hickey on Clojure&amp;#39;s Features and Implementation&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.scala-lang.org/" target="_blank"&gt;Scala&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Yo sigo trabajando en reimplementar las ideas de Clojure en C#, lo llamaba AjClojure, pero Rick Hickey (el creador de Clojure) me pidió que le cambiara el nombre (al fin tengo evidencia de que alguien lee &lt;a href="http://twitter.com/ajlopez" target="_blank"&gt;mi Twitter&lt;/a&gt;!!! :-) Así, que en un rapto de imaginación, se llama AjSharpure. Pueden ir viendo mis avances en:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjSharpure" href="http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjSharpure"&gt;http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjSharpure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Más para ver sobre los lenguajes que me interesan en:   &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/programminglanguages"&gt;http://delicious.com/ajlopez/programminglanguages&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/smalltalk"&gt;http://delicious.com/ajlopez/smalltalk&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/logo"&gt;http://delicious.com/ajlopez/logo&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/scala"&gt;http://delicious.com/ajlopez/scala&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/lisp"&gt;http://delicious.com/ajlopez/lisp&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/forth"&gt;http://delicious.com/ajlopez/forth&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/haskell"&gt;http://delicious.com/ajlopez/haskell&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/python"&gt;http://delicious.com/ajlopez/python&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/ruby"&gt;http://delicious.com/ajlopez/ruby&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/functionalprogramming"&gt;http://delicious.com/ajlopez/functionalprogramming&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/cobol"&gt;http://delicious.com/ajlopez/cobol&lt;/a&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;h3&gt;MVPs&lt;/h3&gt;  &lt;p&gt;El bueno de &lt;a href="http://weblogs.shockbyte.com.ar/rodolfof" target="_blank"&gt;Rodolfo Finochietti&lt;/a&gt; fue nombrado Microsoft MVP por segundo año consecutivo. Felicitaciones @rodolfof! &lt;a href="http://weblogs.shockbyte.com.ar/rodolfof/archive/2009/07/01/mvp-for-another-year.aspx" target="_blank"&gt;MVP for another year&lt;/a&gt;. También felicitaciones para el pibe Woloski, que renovó el nombramiento.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1703061" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/PHP/default.aspx">PHP</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Enlaces+y+Noticias/default.aspx">Enlaces y Noticias</category></item><item><title>Un caso de Uso de AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/30/un-caso-de-uso-de-ajgenesis.aspx</link><pubDate>Tue, 30 Jun 2009 10:04:02 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1697298</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1697298</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/30/un-caso-de-uso-de-ajgenesis.aspx#comments</comments><description>&lt;p&gt;En el grupo Google de Code Generation:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://groups.google.com/group/codegeneration" href="http://groups.google.com/group/codegeneration"&gt;http://groups.google.com/group/codegeneration&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;encuentro este mensaje de Fernando Claverino&lt;/p&gt;  &lt;p&gt;&lt;a href="http://groups.google.com/group/codegeneration/browse_thread/thread/66a64cd0abd63942" target="_blank"&gt;Usos de AjGenesis&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Gracias a Fernando, por compartir su experiencia. Es importante, para &lt;a href="http://ajgenesis.codeplex.com/" target="_blank"&gt;AjGenesis&lt;/a&gt;, que los que lo usen compartan y comenten su experiencia, para poder ir viendo los usos, facilidades y problemas que tenemos con la herramienta. Comento acá gran parte del mensaje. Fernando usa AjGenesis para generar reportes, usando SQL Server por lo que entendí. En proyecto Medusa, estamos también generando reportes usando Reporting Services. Fernando escribe:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Modelo: &lt;/p&gt;    &lt;p&gt;No definimos un archivo models.xml que apunta a cada item del modelo.      &lt;br /&gt;Tenemos una carpeta models y hay una task que la recorre       &lt;br /&gt;recursivamente y levanta todos los archivos del modelo (*.mod.xml).       &lt;br /&gt;Cuando se hace esto, seteamos dinámicamente a cada objeto cargado una       &lt;br /&gt;propiedad con el path relativo, que luego usamos en otras tasks. Los       &lt;br /&gt;artefactos se generan en la misma estructura de carpeta, pero dentro       &lt;br /&gt;de la carpeta build.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Este es un ejemplo de modelo obtenido de otra forma. Podemos partir de uno o varios modelos, obtenerlos de archivos o de otra fuente de información (como una base de datos).&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Plugins: &lt;/p&gt;    &lt;p&gt;Aca estamos haciendo algo de trampa. Si bien todos los artefactos      &lt;br /&gt;generados deberían construirse a partir del modelo, hay algunas cosas       &lt;br /&gt;que son dificiles de modelar. En nuestro caso generamos las consultas       &lt;br /&gt;MDX. Es muy difícil definir un modelo que soporte la riqueza de este       &lt;br /&gt;lenguaje. Asi que lo que hicimos fue definir en el archivo de       &lt;br /&gt;tecnología cual es el plugin a utilizar. El plugin es un template (que       &lt;br /&gt;genera la consulta MDX a partir del modelo). Vi en los ejemplos que en       &lt;br /&gt;la tecnología se suele definir el dialecto (esto sería algo parecido,       &lt;br /&gt;me parece). &lt;/p&gt;    &lt;p&gt;Esta técnica que nosotros llamamos plugin, la usamos siempre que      &lt;br /&gt;queremos generar un caso particular no cubierto por los templates que       &lt;br /&gt;ya tenemos. En el archivo de tecnología podemos definir el onrows,       &lt;br /&gt;oncols y where de la consulta, pero en muchos casos esto varía en       &lt;br /&gt;función del modelo. Es como favorerer convención sobre configuración.       &lt;br /&gt;Si no configuro nada, uso el template que corresponde. Si defino un       &lt;br /&gt;plugin, uso ese. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Interesante. El usar un template dinámicamente, indicándo cuál usar en el propio modelo, en vez de en código duro de tares, es una capacidad que AjGenesis tiene desde el principio. Recuerdo los tiempos de ASP clásico (los noventa), donde se podía incluir otro archivo por nombre en el proceso de un archivo/página, pero el nombre debía ser especificado como constante, no podía ser especificado en ejecución. PHP influyó bastante en el diseño de AjBasic, y se permiten cosas como:&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;     &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;include &lt;span style="color:#006080;"&gt;&amp;quot;Tasks/Build${Technology.Programming.Dialect}.ajg&amp;quot;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Donde el archivo a incluir y procesar como tarea es determinado en ejecución a partir del estado del modelo (o de lo que sea). &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Nivel de abstracción: &lt;/p&gt;

  &lt;p&gt;Aprovechamos la libertad del modelo para trabajar en un nivel más 
    &lt;br /&gt;abstracto. Es decir, en lugar de definir un reporte, definimos una 

    &lt;br /&gt;sección (grupo de reportes) y las posibles navegaciones. La 

    &lt;br /&gt;combinación de estas definen los reportes. Es decir, a partir del 

    &lt;br /&gt;modelo definido, una task lo combina y genera un nuevo modelo a partir 

    &lt;br /&gt;del cual se aplican los templates. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exacto. Podemos elevar el nivel de abstracción en cualquier momento, si no lleva demasiado costo. Es la idea de AjGenesis: podemos modelar entidades, o mensajes, o lo que descubramos en nuestro dominio que es interesante modelar. Y al descubrir eso a modelar, vamos elevando el nivel de abstracción.&lt;/p&gt;

&lt;p&gt;Fernando concluye que no encontraron, en su tiempo, otra herramienta que le diera tanta libertad en la definición de los modelos. Ciertamente, esa libertad es parte del diseño inicial de la herramienta.&lt;/p&gt;

&lt;p&gt;Si Ud. tiene algun caso de uso de AjGenesis, podrá publicar su experiencia?&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1697298" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Modelos y metamodelos en AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/29/modelos-y-metamodelos-en-ajgenesis.aspx</link><pubDate>Mon, 29 Jun 2009 09:28:30 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1697059</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1697059</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/29/modelos-y-metamodelos-en-ajgenesis.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://ajgenesis.codeplex.com/" target="_blank"&gt;AjGenesis&lt;/a&gt; genera código partiendo de un modelo, de libre definición. El modelo se lee desde un archivo .XML (en la versión AjGenesis 0.5) pero también se puede leer desde un archivo de texto. Sobre un modelo sencillo, y sobre la forma de modelo en texto, pueden leer:&lt;/p&gt;  &lt;p&gt;&lt;a title="Generando Código- Hello World con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2006/11/19/generando-c-digo-hello-world-con-ajgenesis.aspx"&gt;Generando Código- Hello World con AjGenesis&lt;/a&gt;    &lt;br /&gt;&lt;a title="Modelo textual para generación de código con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2008/09/29/modelo-textual-para-generaci-243-n-de-c-243-digo-con-ajgenesis.aspx"&gt;Modelo textual para generación de código con AjGenesis&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ha sido una elección inicial de diseño que el modelo sea totalmente libre. El ejemplo más simple de modelo es el que especifica una aplicación Hello World, modelando el mensaje a mostrar:&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;     &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Company&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;ajlopez.com&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Hello, World&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Pero de vez en cuando, nos gustaría tener una especificación, algo que indique qué se puede poner o no en un modelo. Esto serviría, para poder construir, por ejemplo, programas que permitan validar el modelo a usar. Es como cuando uno tiene un Schema o DTD que define cómo es un tipo de documento XML, y es usado por distintos utilitarios, para validar y ayudar en la construcción del documento XML final.&lt;/p&gt;

&lt;p&gt;Como desde el inicio, el modelo no es XML, sino un concepto abstracto, que por razones de implementación, en la versión actual está en XML, nunca agregué o me apoyé en schemas de XML para definir una estructura al modelo, en ningún ejemplo. Pero siempre quise, en algún momento, agregar, opcionalmente, que se pueda definir el modelo. Y que los mismos formatos que AjGenesis usa, puedan servir para definir esos modelos. La descripción del modelo debería ser otro modelo: es un metamodelo expresado de la misma forma a la que ya estamos habituados en AjGenesis (noten que, históricamente, los DTD siempre algo molestaron en el mundo XML, al no ser ellos mismos XMLs, aunque me apresuro a agregar que hubo otras razones más para reemplazarlos).&lt;/p&gt;

&lt;p&gt;Como ejemplo inicial, el modelo de arriba es una instancia de todos los modelos que cumplen con este metamodelo:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SimpleHelloWorld&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Project&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Message&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Company&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Cada modelo tiene Types, que se describen en detalle. Si luego, tenemos un modelo de HelloWorld con múltiples mensajes:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Messages&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Hello, World One&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Hello, World Two&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Hello, World Three&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Messages&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;lo podemos expresar en un metamodelo como:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;MultipleHelloWorld&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Project&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Messages&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;String&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ItemName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Message&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Ahora, tenemos una propiedad que no es simple, sino una lista, de strings. Pero que sus items tienen como nombre a Message (son de la forma &amp;lt;Message&amp;gt;String&amp;lt;/Message&amp;gt;).&lt;/p&gt;

&lt;p&gt;Tomemos un modelo más complejo. Puedo usar el “clásico” modelo de entidades, de:&lt;/p&gt;

&lt;p&gt;&lt;a title="Generando aplicaciones con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2007/06/25/generando-aplicaciones-con-ajgenesis.aspx"&gt;Generando aplicaciones con AjGenesis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El proyecto más simple es AjFirstExample (dos entidades simples):&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;AjFirstExample&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;First Example using AjGenesis&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Prefix&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;AjFE&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Prefix&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Domain&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;com.ajlopez&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Domain&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;CompanyName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;ajlopez&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;CompanyName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entities/Customer.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entities/Supplier.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Lists&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;List&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;List&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Lists&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Forms&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Form&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Form&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Forms&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Views&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;View&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;View&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Views&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Como ejemplo, recordemos la entidad Customer:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;¿Cómo podemos representar esto en un metamodelo? De esta forma:&lt;/div&gt;

&lt;div&gt;&amp;#160;&lt;/div&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;EntityModel&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Project&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Description&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Prefix&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Domain&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;CompanyName&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Model&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Model&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Model&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entities&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entity&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Lists&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;List&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Views&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;View&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Forms&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Form&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entity&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SetName&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Description&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Descriptor&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SetDescriptor&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SqlTable&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Properties&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Property&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Property&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Type&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;SqlType&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;List&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;View&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Form&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;(Faltaría completar los tipos Property, List, View, Form). Y la prueba de fuego, es que el propio metamodelo pueda expresarse como metamodelo:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Metamodel&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Metamodel&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Types&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Type&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Type&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Properties&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;ListOf&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Property&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Property&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;                &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;ListOf&amp;quot;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Reference&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Type&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Types&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Metamodel&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;¿Y para qué tanto trabajo? Para poder usar esa información para validar el modelo, es una razón. Pero también, recordemos, AjGenesis genera código. Podríamos generar el código de un diseñador, de un modelador web o gráfico, que permita:&lt;/p&gt;

&lt;p&gt;- Leer y grabar el modelo
  &lt;br /&gt;- Ver sus datos (gráficamente, o en formularios)

  &lt;br /&gt;- Ingresar su contenido&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesis34.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Por ejemplo, podríamos armar un programa .NET WinForm, que muestre un árbol a la izquierda con la estructura de nuestro modelo (ej. Entidades) y que permita agregar las ramas de ese árbol. Podemos generar las clases tipadas que representen ese modelo en memoria. Y los códigos de los serializadores del modelo en XML&amp;#160; o en texto o en lo que elijamos. También se podría leer el metamodelo desde un programa genérico, y que éste maneje el mostrado y el ingreso de datos del modelo, dinámicamente, en runtime:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesis35.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Pero todo esto no es necesario para trabajar hoy por hoy con AjGenesis. Quería mencionarlo, porque lo tengo en suspenso desde hace unos años como idea. No es un tema prioritario por ahora, lo que más se necesita es documentación, ejemplos mejorados y ejemplos con nuevas tecnologías.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1697059" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Transformando plantillas en AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/27/transformando-plantillas-en-ajgenesis.aspx</link><pubDate>Sat, 27 Jun 2009 06:59:32 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1696836</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1696836</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/27/transformando-plantillas-en-ajgenesis.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://ajgenesis.codeplex.com/" target="_blank"&gt;AjGenesis&lt;/a&gt; se base en modelo libre, y usa plantillas (templates) para facilitar la descripción y generación de un archivo de texto final. La forma más simple de transformar un archivo de plantilla en un archivo destino es con un comando como:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;AjGenesis.Console Model.xml ModuleVb.tpl HelloWorld.vb&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Donde Model.xml puede tener&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;     &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Company&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;ajlopez.com&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Hola, Mundo&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Message&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Author&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Pepe&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Author&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;ModuleVb.tpl es la plantilla:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; Automatically generated by AjGenesis&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; http://www.ajlopez.com/ajgenesis&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; Company ${Project.Company}&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;Module&lt;/span&gt; Module1&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; Main()&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        System.Console.WriteLine(&lt;span style="color:#006080;"&gt;&amp;quot;${Project.Message}&amp;quot;&lt;/span&gt;)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Module&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Produciendo HelloWorld.vb&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; Automatically generated by AjGenesis&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; http://www.ajlopez.com/ajgenesis&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39; Company ajlopez.com&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;Module&lt;/span&gt; Module1&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; Main()&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        System.Console.WriteLine(&lt;span style="color:#006080;"&gt;&amp;quot;Hola, Mundo&amp;quot;&lt;/span&gt;)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Module&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;(Los ejemplos de HelloWorld que describo los pueden encontrar en la versión liberada 0.5, dentro del directorio examples, hay varios directorios HelloWorld*) (Más detalle en &lt;a title="Generando Código- Hello World con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2006/11/19/generando-c-digo-hello-world-con-ajgenesis.aspx"&gt;Generando Código- Hello World con AjGenesis&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;La otra opción es desde una tarea, programáticamente:&lt;/p&gt;

&lt;p&gt;AjGenesis.Console Model.xml Build.ajg&lt;/p&gt;

&lt;p&gt;donde Build.ajg es un archivo de tareas, escrito en AjGenesis:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;PrintLine &lt;span style="color:#006080;"&gt;&amp;quot;Generating HelloWorld&amp;quot;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;ModuleVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;HelloWorld.vb&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;El objeto TransformerManager es un objeto auxiliar, de los que están ya definidos en AjGenesis, para que podamos aprovecharlo. Su “gran método” es .Transform que toma:&lt;/p&gt;

&lt;p&gt;- Nombre del archivo de plantilla
  &lt;br /&gt;- Nombre del archivo a generar

  &lt;br /&gt;- El Environment&lt;/p&gt;

&lt;p&gt;Environment es otro objeto predefinido, que es un diccionario donde están definidos los nombres y valores de variables en curso. Tanto “TransformerManager” como “Environment” son claves/keys dentro de ese directorio. Cuando uno escribe en AjBasic:&lt;/p&gt;

&lt;p&gt;&lt;font face="Consolas"&gt;a = 1&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;agrega automáticamente la entrada “a” y el valor 1 en el Environment.&lt;/p&gt;

&lt;p&gt;Es común que la transformación de plantillas se escriba en tareas más complejas. Fragmento de un ejemplo (ver examples/HelloWorldNet20/Tasks/Build.ajg):&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;PrintLine &lt;span style="color:#006080;"&gt;&amp;quot;Creating Solution File&amp;quot;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\Solution.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}.sln&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;PrintLine &lt;span style="color:#006080;"&gt;&amp;quot;Creating VB.Net Project&amp;quot;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\ModuleVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Vb\Module1.vb&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\AssemblyInfoVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Vb\My Project\AssemblyInfo.vb&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\VbProject.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Vb\${Project.Name}Vb.vbproj&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39;TransformerManager.Transform(&amp;quot;Templates\VbProjectUser.tpl&amp;quot;, &amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Vb\${Project.Name}Vb.vbproj.user&amp;quot;, Environment)&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;PrintLine &lt;span style="color:#006080;"&gt;&amp;quot;Creating C# Project&amp;quot;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\ClassCs.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Cs\Program.cs&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\AssemblyInfoCs.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Cs\Properties\AssemblyInfo.cs&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformerManager.Transform(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\CsProject.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Cs\${Project.Name}Cs.csproj&amp;quot;&lt;/span&gt;, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#008000;"&gt;&amp;#39;TransformerManager.Transform(&amp;quot;Templates\CsProjectUser.tpl&amp;quot;, &amp;quot;${Project.BuildDir}\${Project.Name}\${Project.Name}Cs\${Project.Name}Cs.csproj.user&amp;quot;, Environment)&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Un problema que encontré, es que si regeneramos desde el modelo todos estos archivos finales, los pisamos, los creamos de nuevo. Supongamos que sólo queremos generar el archivo destino, si no existe de antes (una táctica destinada a preservar el archivo destino, por si lo hemos modificado nosotros). En un proyecto (el proyecto Medusa que mencionó en &lt;a title="Generando y regenerando texto y código con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2009/06/26/generando-y-regenerando-texto-y-c-243-digo-con-ajgenesis.aspx"&gt;Generando y regenerando texto y código con AjGenesis&lt;/a&gt;, &lt;a title="Generación de código con AjGenesis para Mere Mortals Framework" href="http://msmvps.com/blogs/lopez/archive/2009/06/22/code_2D00_generation_2D00_for_2D00_mere_2D00_mortals_2D00_framework.aspx"&gt;Generación de código con AjGenesis para Mere Mortals Framework&lt;/a&gt;), usamos esta rutina, que definimos en AjBasic:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;sub&lt;/span&gt; TransformNewFile(tpl, target, tm, env)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; System.IO.File.Exists(target) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        tm.Transform(tpl, target, env)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;sub&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Que invocamos, por ejemplo, con:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformNewFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\ClassPartialVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}BO\${Project.Name}BO\${Table.Name}\${Table.Name}.Partial.vb&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Pero nos ha resultado muy útil, tener otra rutina, que reemplaza el archivo destino, pero si éste existe, solamente lo reemplaza si su contenido actual es distinto del contenido nuevo que vamos a generar:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;sub&lt;/span&gt; TransformFile(tpl, target, tm, env)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; System.IO.File.Exists(target) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        target2 = target &amp;amp; &lt;span style="color:#006080;"&gt;&amp;quot;.tmp&amp;quot;&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        tm.Transform(tpl, target2, env)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        content1 = System.IO.File.ReadAllText(target)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        content2 = System.IO.File.ReadAllText(target2)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; content1 &amp;lt;&amp;gt; content2 &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;            System.IO.File.Copy(target2, target, &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;        &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        System.IO.File.Delete(target2)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;        tm.Transform(tpl, target, env)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;sub&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Se puede mejorar (usar un stream en memoria, en lugar de un archivo temporal). Un ejemplo de uso:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\DefaultAspx.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\Default.aspx&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\DefaultAspxVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\Default.aspx.vb&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\GlobalAsax.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\Global.asax&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\MasterPageMainMaster.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\MasterPageMain.master&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\MasterPageMainMasterVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\MasterPageMain.master.vb&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\UserLoginAspx.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\UserLogin.aspx&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\UserLoginAspxVb.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\UserLogin.aspx.vb&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;


    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;TransformFile(&lt;span style="color:#006080;"&gt;&amp;quot;Templates\WebConfig.tpl&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;.\${Project.Name}Web\web.config&amp;quot;&lt;/span&gt;,TransformerManager, Environment)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;La rutina TransformFile nos ha resultado muy útil, al usar un sistema de repositorio de código. Cuando cambiamos el modelo, y regeneramos todo lo que determinamos que se genera (contrapuesto a lo que tenemos como archivos manuales en nuestra solución), ahora, cuando vamos a guardar en el repositorio de código, los archivos que no cambiaron su contenido (ni su fecha y hora de grabación) son los que se envían al servidor. Esto ha simplificado todos los commits, y hasta sirve para darse cuenta cuál es el efecto de un cambio en el modelo inicial: el propio software de repositorio de código nos avisa qué archivos quedaron cambiados.&lt;/p&gt;

&lt;p&gt;Esas dos rutinas las pusimos en un archivo Templates\Utilities.tpl y las incluimos en nuestras tareas con:&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div id="codeSnippet" style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:#f4f4f4;text-align:left;border-bottom-style:none;"&gt;
    &lt;pre style="padding-right:0px;padding-left:0px;font-size:8pt;padding-bottom:0px;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;border-top-style:none;line-height:12pt;padding-top:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;border-right-style:none;border-left-style:none;background-color:white;text-align:left;border-bottom-style:none;"&gt;include &lt;span style="color:#006080;"&gt;&amp;quot;Templates/Utilities.tpl&amp;quot;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Seguramente, comenzaran a aparecer en los ejemplos que vaya publicando.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;

  &lt;br /&gt;&lt;a href="http://www.facebook.com/ajlopez"&gt;http://www.facebook.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1696836" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Generando y regenerando texto y código con AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/26/generando-y-regenerando-texto-y-c-243-digo-con-ajgenesis.aspx</link><pubDate>Fri, 26 Jun 2009 09:25:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1696778</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1696778</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/26/generando-y-regenerando-texto-y-c-243-digo-con-ajgenesis.aspx#comments</comments><description>&lt;p&gt;En estos d&amp;iacute;as de Junio, se ha desarrollado el interesant&amp;iacute;simo congreso de generaci&amp;oacute;n de c&amp;oacute;digo (digamos, &amp;ldquo;el mundial&amp;rdquo; del Code Generation), con un programa envidiable:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.codegeneration.net/cg2009/programme.php" title="Code Generation 2009 - Daily Event Programme"&gt;Code Generation 2009 - Daily Event Programme&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Encuentro en Twitter &lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesis33.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;(uso &lt;a target="_blank" href="http://tweetdeck.com/beta/"&gt;TweetDeck&lt;/a&gt;, con search &amp;ldquo;code generation&amp;rdquo;)&lt;/p&gt;
&lt;p&gt;el enlace a este post de &lt;a target="_blank" href="http://www.metacase.com/stevek.html"&gt;Steven Kelly&lt;/a&gt; (de &lt;a target="_blank" href="http://www.metacase.com/"&gt;MetaCase&lt;/a&gt;) sobre&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://www.metacase.com/blogs/stevek/blogView?showComments=true&amp;amp;entry=3423259520"&gt;Code Generation 2009 round-up&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;donde levanta y comenta impresiones sobre la conferencia. Curiosamente (o no, ya a esta altura), Kelly tambi&amp;eacute;n usa Twitter para tomar feedback:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://twitter.com/EelcoVisser"&gt;&lt;img align="left" src="http://s3.amazonaws.com/twitter_production/profile_images/135809182/self_normal.jpg" alt="" /&gt;&lt;/a&gt; &lt;a href="http://twitter.com/EelcoVisser/statuses/2220107629"&gt;EelcoVisser&lt;/a&gt;: keynote by @markusvoelter and Steven Kelly at #cg2009: great overview of issues in model-driven development &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;a href="http://twitter.com/HBehrens"&gt;&lt;img align="left" src="http://s3.amazonaws.com/twitter_production/profile_images/87000893/HeikoProfil_normal.jpg" alt="" /&gt;&lt;/a&gt; HBehrens: Steven Kelly at #cg2009 keynote: &amp;quot;wizard based generators create a large legacy application you&amp;#39;ve never seen before&amp;quot; &lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A esta &amp;uacute;ltima referencia, Kelly comenta y responde:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The reference was to vendor-supplied wizards, often found in IDEs or SDKs, that create skeleton applications for you based on your input. Since the vendors take pride in just how much boilerplate they can spew out, you&amp;#39;re left with a mass of generated code that you&amp;#39;ve never seen before, but must extend with your own code. Worse, you&amp;#39;re responsible for maintaining the whole ensuing mixture, and there&amp;#39;s no chance of re-running the wizard to change some of the choices -- at least not without losing or invalidating the code you&amp;#39;ve added. That&amp;#39;s in sharp contrast with generation in DSM, where your input is in the form of a model which you can edit at any time. You get the speed of generation but can remain at a high level of abstraction throughout&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Con DSM se refiere a Domain Specific Model. Pueden ver mis enlaces en &lt;a href="http://delicious.com/ajlopez/dsm"&gt;http://delicious.com/ajlopez/dsm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;M&amp;aacute;s info visitando el &lt;a href="http://www.dsmforum.org/" title="DSM Forum"&gt;DSM Forum&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mi proyecto de c&amp;oacute;digo abierto &lt;a target="_blank" href="http://ajgenesis.codeplex.com/"&gt;AjGenesis&lt;/a&gt; est&amp;aacute; basado en modelo, en modelos de libre definici&amp;oacute;n, justamente, orientados al dominio que uno quiera modelar. No son modelos gr&amp;aacute;ficos, que son m&amp;aacute;s &amp;ldquo;fancy&amp;rdquo;, pero hasta ahora, me han resultado &amp;uacute;tiles y flexibles. Traduciendo la cita de arriba, una de las quejas de Kelly es que hay herramientas que generan c&amp;oacute;digo, como un wizard dentro de un entorno de desarrollo, pero luego, cuando trabaja agregando c&amp;oacute;digo propio en la soluci&amp;oacute;n, ya no puede volver a regenerar c&amp;oacute;digo. Y que &amp;eacute;l ve una soluci&amp;oacute;n si partimos de un modelo espec&amp;iacute;fico de dominio. El modelo a partir puede ser la base de datos, un modelo abstracto de entidades, un modelo m&amp;aacute;s orientado al sistema que estamos tratando de construir (me imagino modelos dedicados a CRM, o a mercados a&amp;uacute;n m&amp;aacute;s verticales).&lt;/p&gt;
&lt;p&gt;Bueno, el tema da para discutir. Pr&amp;aacute;cticamente, ning&amp;uacute;n modelo produce todo lo que queremos, as&amp;iacute; que tenemos que dejar en nuestra aplicaci&amp;oacute;n, lugares, puntos de extensibilidad manual, forma de agregar c&amp;oacute;digo nuestro, sin que tengamos que perder lo generado. Y que sigamos teniendo la posibilidad, al cambiar el modelo inicial, de volver a generar la parte autom&amp;aacute;tica, sin perder lo agregado manualmente.&lt;/p&gt;
&lt;p&gt;Desde hace algunos a&amp;ntilde;os, incluyo este &amp;ldquo;slide&amp;rdquo; en mis charlas sobre el tema. Explico que uno no genera todo, y que tiene que estar claro, cuales archivos de texto son generados, y luego regenerados desde el modelo cuantas veces uno quiera, cu&amp;aacute;les son generados de una sola vez, y cu&amp;aacute;les son agregados manualmente:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesis32.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Uno tiene que decidir qu&amp;eacute; genera desde el modelo, y qu&amp;eacute; genera o agrega manualmente. Me encontrado con gente que utiliz&amp;oacute; AjGenesis s&amp;oacute;lo para generar los procedimientos almacenados. En el proyecto Medusa (que mencion&amp;eacute; en mi post&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2009/06/22/code_2D00_generation_2D00_for_2D00_mere_2D00_mortals_2D00_framework.aspx" title="Generaci&amp;oacute;n de c&amp;oacute;digo con AjGenesis para Mere Mortals Framework"&gt;Generaci&amp;oacute;n de c&amp;oacute;digo con AjGenesis para Mere Mortals Framework&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;estamos adoptando una soluci&amp;oacute;n en el sentido de la figura. Cuando lanzamos la generaci&amp;oacute;n autom&amp;aacute;tica desde el modelo, que incluye:&lt;/p&gt;
&lt;p&gt;- Generaci&amp;oacute;n de scripts de generaci&amp;oacute;n de las tablas &lt;br /&gt;- Generaci&amp;oacute;n de los procedimientos almacenados &lt;br /&gt;- Generaci&amp;oacute;n de un proyecto de Business Objects (como pide el Mere Mortals Framework) &lt;br /&gt;- Generaci&amp;oacute;n de una aplicaci&amp;oacute;n web ASP.NET (usando nuevamente el Mere Mortals Framework, por ejemplo, sus controles web)&lt;/p&gt;
&lt;p&gt;hemos codificado las tareas, de tal forma que:&lt;/p&gt;
&lt;p&gt;- Hay archivos que siempre se generan (se &amp;ldquo;pisa&amp;rdquo; la anterior versi&amp;oacute;n, pero solamente si la nueva tiene un contenido distinto) &lt;br /&gt;- Hay archivos que no se generan si ya existen (pocos archivos, que se han decidido ser &amp;ldquo;one shoot&amp;rdquo;, generados de una sola vez, y no m&amp;aacute;s) &lt;br /&gt;- Hay archivos que se respetan y no se generan (archivos que vamos agregando a los proyectos que vamos armando)&lt;/p&gt;
&lt;p&gt;Estamos usando .NET. En el caso 2, caen las clases parciales, que es una forma de seguir especificando una clase, en un archivo adicional al original. En otras tecnolog&amp;iacute;as, podr&amp;iacute;amos generar un archivo ClaseBase generado autom&amp;aacute;ticamente, y un ClaseReal donde pudi&amp;eacute;ramos luego poner todo nuestro c&amp;oacute;digo manual.&lt;/p&gt;
&lt;p&gt;Con esta estrategia, hemos alcanzado hasta ahora, gran parte de lo que imaginaba en la figura de arriba: poder generar siempre desde el modelo, sin tener que perder lo que ya tenemos.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1696778" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Mere+Mortals+Framework/default.aspx">Mere Mortals Framework</category></item><item><title>Generación de código con AjGenesis para Mere Mortals Framework</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/22/code_2D00_generation_2D00_for_2D00_mere_2D00_mortals_2D00_framework.aspx</link><pubDate>Mon, 22 Jun 2009 10:37:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1696161</guid><dc:creator>lopez</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1696161</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/22/code_2D00_generation_2D00_for_2D00_mere_2D00_mortals_2D00_framework.aspx#comments</comments><description>&lt;p&gt;En un proyecto en el que estoy trabajando, el equipo &amp;aacute;gil del que soy miembro est&amp;aacute; desarrollando una aplicaci&amp;oacute;n completa de salud (es el Medusa Project), usando Mere Mortals framework como base para objestos de negocios, persistencia, y presentaci&amp;oacute;n en WinForm y ASP.NET. Pueden bajarse una versi&amp;oacute;n de prueba de este framework en:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.oakleafsd.com/" title="http://www.oakleafsd.com/"&gt;http://www.oakleafsd.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm01.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Hay una lista de caracter&amp;iacute;sticas en&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.oakleafsd.com/MMNetFeatures/pgMMNetFeatures.htm" title="http://www.oakleafsd.com/MMNetFeatures/pgMMNetFeatures.htm"&gt;http://www.oakleafsd.com/MMNetFeatures/pgMMNetFeatures.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pueden bajarse la gu&amp;iacute;a de desarrollo de&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.oakleafsd.com/Download%20files/MMNetDevGuide35.zip" title="MM .NET Developer&amp;#39;s Guide"&gt;MM .NET Developer&amp;#39;s Guide&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El framework fue desarrollado por Kevin McNeish, Microsoft MVP, presidente y arquicecto jefe de Oak Leaf Enterprise. El framework soporta entidades tipadas, pero por abajo, est&amp;aacute; basado en datasets. Podemos generar un proyecto de business objects con templates de VS que vienen con el framework, y tiene un generador de c&amp;oacute;digo provisto por el producto, podemos generar las clases de objetos de negocios, derivadas desde la base de datos.&lt;/p&gt;
&lt;p&gt;En mi equipo, alimentamos metadata leyendo informaci&amp;oacute;n de la base de datos, y con esa informaci&amp;oacute;n, generamos una aplicaci&amp;oacute;n web completa en ASP.NET, un librer&amp;iacute;a de objetos de negocios, procedimientos almacenados, y DDL para regenerar la base. Todo usando &lt;a target="_blank" href="http://ajgenesis.codeplex.com/"&gt;AjGenesis&lt;/a&gt;, mi proyecto abierto de generaci&amp;oacute;n de c&amp;oacute;digo. Espero escribir alg&amp;uacute;n post sobre esa experiencia. Las tareas y plantillas que usamos, han sido derivadas del ejemplo:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2008/04/21/ajgenesis-generating-the-model-from-the-database/" title="AjGenesis- Generating the model from the database"&gt;AjGenesis- Generating the model from the database&lt;/a&gt; &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/11/25/ajgenesis-modelo-desde-la-base-de-datos.aspx" title="AjGenesis- Modelo desde la Base de Datos"&gt;AjGenesis- Modelo desde la Base de Datos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En esto post, uso otra aproximaci&amp;oacute;n, m&amp;aacute;s cl&amp;aacute;sica en los ejemplos de AjGenesis: partir de un modelo abstracto, generando desde all&amp;iacute;:&lt;/p&gt;
&lt;p&gt;- Scripts para crear la base de datos &lt;br /&gt;- Business Objects a la Mere Mortals en una librer&amp;iacute;a de clases &lt;br /&gt;- Proyecto WinForm con formularios de mantenimiento&lt;/p&gt;
&lt;p&gt;Escrib&amp;iacute; sobre generaci&amp;oacute;n de aplicaciones en distintas tecnolog&amp;iacute;as, desde un modelo abstracto, en:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2007/11/12/application-generation-using-ajgenesis/" title="Application Generation using AjGenesis"&gt;Application Generation using AjGenesis&lt;/a&gt; &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/06/25/generando-aplicaciones-con-ajgenesis.aspx" title="Generando aplicaciones con AjGenesis"&gt;Generando aplicaciones con AjGenesis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;pero recuerden: AjGenesis se basa en modelos de libre definici&amp;oacute;n. Podemos modelar lo que querramos. Como ejemplo trivial:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2007/01/29/code-generation-with-ajgenesis-a-hello-world-application/" title="Code Generation with AjGenesis- A Hello World application"&gt;Code Generation with AjGenesis- A Hello World application&lt;/a&gt; &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2006/11/19/generando-c-digo-hello-world-con-ajgenesis.aspx" title="Generando C&amp;oacute;digo- Hello World con AjGenesis"&gt;Generando C&amp;oacute;digo- Hello World con AjGenesis&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;El modelo&lt;/h3&gt;
&lt;p&gt;Pueden bajar el ejemplo desde la p&amp;aacute;gina de ejemplos del proyecto, en Codeplex:&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://ajgenesis.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=7261#DownloadId=72477"&gt;MereMortalsExamples200906.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contiene:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm02.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;El modelo resido en el archivo Projects/AjFirstExample/Project.xml&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;AjFirstExample&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;First Example using AjGenesis&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Prefix&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;AjFE&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Prefix&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Domain&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;com.ajlopez&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Domain&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;CompanyName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;ajlopez&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;CompanyName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entities/Customer.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Entities/Supplier.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Lists&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;List&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;List&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Lists&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Forms&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Form&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Form&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Forms&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Views&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;View&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;View&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Views&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;p&gt;Referencia a dos entidades, Customer and Supplier. La entidad Customer:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customer&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customer Entity&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetName&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Descriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customer&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Descriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetDescriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SetDescriptor&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlTable&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Customers&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlTable&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Id&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Id&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Name&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Text&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;varchar(200)&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Address&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Text&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;text&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Notes&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;Text&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Type&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;            &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;text&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;SqlType&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Property&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Properties&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;p&gt;Hay un modelo que describe la tecnolog&amp;iacute;a que vamos a usar en Projects/AjFirstExample/Technologies/VbNet3.xml:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Technology&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Programming&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Dialect&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;VbNet3&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Dialect&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Programming&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Database&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Dialect&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;MsSql&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Dialect&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;AjFirstExampleMM&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;(local)&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Host&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Database&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Technology&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;p&gt;Puede cambiar el host a .\SQLEXPRESS si no tiene un servidor MS SQL. Puede agregar &amp;lt;Username&amp;gt; y &amp;lt;Password&amp;gt; si quiere usar la seguridad de SQL. Si no est&amp;aacute;n, el ejemplo usa seguridad integrada de Windows.&lt;/p&gt;
&lt;h3&gt;Generando la aplicaci&amp;oacute;n&lt;/h3&gt;
&lt;p&gt;Debe bajarse la versi&amp;oacute;n liberada actual de AjGenesis, la 0.5, desde &lt;a href="http://ajlgenesis.codeplex.com"&gt;http://ajlgenesis.codeplex.com&lt;/a&gt;. Agregue el directorio bin a su lista de directorios en PATH. Hecho esto, podemos ejecutar desde el directorio del ejemplo:&lt;/p&gt;
&lt;p&gt;GenerateProject.cmd AjFirstExample VbNet3&lt;/p&gt;
&lt;p&gt;El primer par&amp;aacute;metro es el nombre del proyecto, el segundo es la tecnolog&amp;iacute;a a usar. El comando invoca&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;"&gt;AjGenesis.Console Projects\%Project%\Project.xml tasks\BuildProject.ajg  Projects\%Project%\Technologies\%Technology%.xml tasks\BuildTechnology.ajg tasks\BuildProg.ajg tasks\BuildSql.ajg&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Esto lee el modelo de proyecto, ejecuta la tarea BuildProject, carga el modelo de tecnolog&amp;iacute;a, ejecuta la tarea de BuildTechnology. Finalmente, la tarea BuildProg genera el c&amp;oacute;digo, y BuildSql genera el DDL necesario para crear la base de datos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm03.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Se crea un nuevo directorio, Build, que contiene el resultado:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm04.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;En el directorio Sql, encontramos el comando ExecuteAll.cmd que crea la base de datos&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm05.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Podemos ejecutarlo con un par&amp;aacute;metro, especificando ah&amp;iacute; el servidor:&lt;/p&gt;
&lt;p&gt;ExecuteAll.cmd Bombadil&lt;/p&gt;
&lt;p&gt;Si ejecutamos el comando sin par&amp;aacute;metro, usa el host especificado en el modelo de tecnolog&amp;iacute;a.&lt;/p&gt;
&lt;p&gt;En directorio Src encontraremos reci&amp;eacute;n generada una soluci&amp;oacute;n .NET completa, con dos proyectos:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm06.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Podemos levantarla en Visual Studio 2008, y compilarla (necesitamos tener una versi&amp;oacute;n de Mere Mortals Framework instalada).&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm07.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;La librer&amp;iacute;a de clases contiene definiciones de objetos de negocios de Mere Mortals (usando clases parciales, clases de acceso a datos usando procedimientos almacenados, reglas&amp;hellip;.)&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm08.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;El proyecto WinForm tiene dos formularios de mantenimiento, para Customers y Suppliers:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm09.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Bueno, no ser&amp;aacute; &amp;ldquo;uy que bruto, que aplicaci&amp;oacute;n&amp;rdquo;&amp;hellip;. :-)&amp;hellip; pero ejecuta:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/mm10.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Si no quieren seguir estos pasos, pueden bajarse la soluci&amp;oacute;n generada, de mi Skydrive&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/DotNet/AjFirstExampleMereMortals.zip"&gt;AjFirstExampleMereMortals.zip&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p&gt;Usando un modelo abstracto, podemos generar los artefactos de textos que requiere el framework de Mere Mortals (o cualquier otro framework o tecnolog&amp;iacute;a como describ&amp;iacute; en &lt;a href="http://msmvps.com/blogs/lopez/archive/2009/06/14/generaci-243-n-de-c-243-digo-ajgenesis-y-dunga-dunga-a-la-tecnolog-237-a.aspx" title="Generaci&amp;oacute;n de c&amp;oacute;digo, AjGenesis, y Dunga dunga a la tecnolog&amp;iacute;a"&gt;Generaci&amp;oacute;n de c&amp;oacute;digo, AjGenesis, y Dunga dunga a la tecnolog&amp;iacute;a&lt;/a&gt;). Con clases parciales, y archivos separados, podemos regenerar c&amp;oacute;digo desde el modelo, sin perder el c&amp;oacute;digo manual que hayamos agregado. Podemos extender el c&amp;oacute;digo generado agregando validaciones autom&amp;aacute;ticos, nuevas reglas, y cualquier est&amp;aacute;ndar de codificaci&amp;oacute;n que estemos usando.&lt;/p&gt;
&lt;p&gt;Pero el punto principal, para m&amp;iacute;, es que usando un modelo abstracto, estamos separando el n&amp;uacute;cleo importante de nuestra aplicaci&amp;oacute;n, de los detalles t&amp;eacute;cnicos&amp;acute;. Podemos regenerar la aplicaci&amp;oacute;n usando otro framework, otros lenguajes, otras tecnolog&amp;iacute;as, y nuestro modelo podr&amp;iacute;a ser el mismo. El modelo describe lo que queremos. Tareas, y plantillas terminan siendo un sistema experto, que conoce COMO obtener lo que queremos como aplicaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.ajlopez.com/en"&gt;http://www.ajlopez.com/en&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1696161" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Mere+Mortals+Framework/default.aspx">Mere Mortals Framework</category></item><item><title>Generación de Código, AjGenesis y AjBasic</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/15/generaci-243-n-de-c-243-digo-ajgenesis-y-ajbasic.aspx</link><pubDate>Mon, 15 Jun 2009 16:09:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1695470</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1695470</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/15/generaci-243-n-de-c-243-digo-ajgenesis-y-ajbasic.aspx#comments</comments><description>&lt;p&gt;En el post que coment&amp;eacute; ayer&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/08/02/sobre-la-generaci-243-n-de-c-243-digo.aspx"&gt;Sobre la generaci&amp;oacute;n de c&amp;oacute;digo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;el comentador &lt;a href="http://emmanueloga.blogspot.com"&gt;Emmanuel&lt;/a&gt; escrib&amp;iacute;a:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pregunta: Ya que tu apodo es &amp;quot;java&amp;quot; :), porque no utilizar StringTemplate en vez de crear tu propio generador?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.stringtemplate.org/"&gt;http://www.stringtemplate.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://antlr.org/about.html"&gt;http://antlr.org/about.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;La respuesta es corta y es larga. Si vieron los ejemplos que he publicado, y c&amp;oacute;mo funciona AjGenesis:&lt;/p&gt;
&lt;li&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx"&gt;AjGenesis&lt;/a&gt; (posts en espa&amp;ntilde;ol con ejemplos)&lt;/li&gt;
&lt;p&gt;sabr&amp;aacute;n que he implementado mi propio lenguaje interpretado AjBasic (con una implementaci&amp;oacute;n ahora separada en &lt;a href="http://code.google.com/p/ajbasic/"&gt;http://code.google.com/p/ajbasic/&lt;/a&gt;), que ahora est&amp;aacute; evolucionando a ser un lenguaje, con el mismo n&amp;uacute;cleo que el AjSharp:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/09/26/ajsharp-un-int-233-rprete-a-la-c-sharp-trabajo-en-progreso.aspx"&gt;AjSharp: un int&amp;eacute;rprete a la C Sharp, trabajo en progreso&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n est&amp;aacute; pensado que se pueda utilizar otro lenguaje para los templates:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2006/10/02/Escribiendo-templates-de-AjGenesis-en-otros-lenguajes.aspx"&gt;Escribiendo templates de AjGenesis en otros lenguajes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pero hoy por hoy, se puede usar s&amp;oacute;lo AjBasic en la generaci&amp;oacute;n de c&amp;oacute;digo de AjGenesis. Lo adopt&amp;eacute;, porque pienso que el lenguaje de templates Y DE TAREAS (porque eso tiene AjGenesis, no s&amp;oacute;lo es templates, sino tambi&amp;eacute;n contiene c&amp;oacute;digo que organiza la generaci&amp;oacute;n de artefactos de textos), es tan fundamental en lo que quer&amp;iacute;a construir, que no pens&amp;eacute; en montarme sobre otro proyecto. Creo que, pasado el tiempo, ha sido una sabia decisi&amp;oacute;n. Veo que el proyecto actual, tengo un dominio total sobre algo que es parte del n&amp;uacute;cleo de AjGenesis.&lt;/p&gt;
&lt;p&gt;Recordemos que AjBasic se usa en las tareas. Y permite el uso de objetos din&amp;aacute;micos. Por ejemplo:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; Project.Title &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    Project.Title = Project.Name&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;not&lt;/span&gt; Project.Version &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    Project.Version = &lt;span style="color:#006080;"&gt;&amp;quot;1.0.*&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Este ejemplo, tomado de una tarea t&amp;iacute;pica de los ejemplos que vienen incluidos con el sistema, muestra dos caracter&amp;iacute;sticas muy usadas: una, preguntar por Project.Title y si Project o Project.Title no est&amp;aacute;n definidos, eso vale falso para el if (una extensi&amp;oacute;n de ideas de lenguajes anteriores como PHP). Me evito preguntar por Nothing o cosas as&amp;iacute;. Y otra caracter&amp;iacute;stica: como Project es un objeto din&amp;aacute;mico, le puedo agregar propiedades en cualquier momento.&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n se le pueden sembrar, en el environment (entorno de valores definidos en el sistema en ejecuci&amp;oacute;n), objetos .NET &amp;ldquo;duros&amp;rdquo;, y el lenguaje los maneja por reflection.&lt;/p&gt;
&lt;p&gt;Esto es algo que todo lenguaje interpretado de hoy en d&amp;iacute;a deber&amp;iacute;a tener: explotaci&amp;oacute;n f&amp;aacute;cil y directa de cualquier framework de clases que lo sostenga. He programado AjBasic de tal forma que podr&amp;iacute;a reimplementarlo f&amp;aacute;cilmente en Java, usando entonces la librer&amp;iacute;a de clases de Java. Y tiene una estructura (int&amp;eacute;rprete que ejecuta un &amp;aacute;rbol abstracto), que puede reimplementarse en cualquier lenguaje en que sea necesario. Por ahora, no he visto la necesidad de hacerlo. Estas razones hacen que no me haya preocupado por compilarlo a bytecodes de la m&amp;aacute;quina virtual, usando CodeDom, o Emit, porque no es el n&amp;uacute;cleo de lo que estoy persiguiendo: no necesito velocidad, necesito flexibilidad.&lt;/p&gt;
&lt;p&gt;Otro peque&amp;ntilde;o e importante detalle:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;include &lt;span style="color:#006080;"&gt;&amp;quot;Tasks/Build${Technology.Programming.Dialect}.ajg&amp;quot;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Este tipo de instrucci&amp;oacute;n, de nuevo inspirado en PHP, permite la inclusi&amp;oacute;n din&amp;aacute;mica de c&amp;oacute;digo. Dependiendo de lo que diga el modelo de tecnolog&amp;iacute;a, puedo incluir en la ejecuci&amp;oacute;n a Tasks/BuildCSharp2.ajg o a Tasks/BuildJava.ajg o lo que sea, din&amp;aacute;micamente.&lt;/p&gt;
&lt;p&gt;Y en un proyecto actual, del que espero postear en breve, hasta puedo incluir en la expansi&amp;oacute;n de un archivo de template, a otro, din&amp;aacute;micamente:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div style="font-size:8pt;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;" id="codeSnippet"&gt;
&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System.Collections.Generic&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; System.Text&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; OakLeaf.MM.Main.Business&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; OakLeaf.MM.Main.Collections&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;Imports&lt;/span&gt; OakLeaf.MM.Main.Data&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;Partial &lt;span style="color:#0000ff;"&gt;Public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Class&lt;/span&gt; ${Table.SqlName}&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#008000;"&gt;&amp;#39;&amp;#39;&amp;#39; &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#008000;"&gt;&amp;#39;&amp;#39;&amp;#39; Hook method automatically executed from the mmBusinessObject constructor&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#008000;"&gt;&amp;#39;&amp;#39;&amp;#39; &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#008000;"&gt;&amp;#39;&amp;#39;&amp;#39; &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;Protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Overridable&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt; HookPartialConstructor()&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;        &lt;span style="color:#008000;"&gt;&amp;#39;&amp;#39; Place code here to be executed when the business object instantiates&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;Sub&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;&amp;lt;#&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; System.IO.File.Exists(&lt;span style="color:#006080;"&gt;&amp;quot;Templates/${Table.Name}PartialVb.tpl&amp;quot;&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;then&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;        include(&lt;span style="color:#006080;"&gt;&amp;quot;Templates/${Table.Name}PartialVb.tpl&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:#f4f4f4;text-align:left;border-style:none;padding:0px;"&gt;#&amp;gt;        &lt;/pre&gt;

&lt;pre style="font-size:8pt;margin:0em;overflow:visible;width:100%;color:black;direction:ltr;line-height:12pt;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;background-color:white;text-align:left;border-style:none;padding:0px;"&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt; Class&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Y tengo m&amp;aacute;s usos para un lenguaje flexible, dentro de AjGenesis. La idea final, es usarlo para tomar decisiones, para convertir el proceso de generaci&amp;oacute;n, en un sistema experto. Algunas decisiones ya toma. Por ejemplo, dada un entidad X, que tiene relaciones con otras, puede decidir incluir una p&amp;aacute;gina de &amp;ldquo;ver entidad X&amp;rdquo; que tenga enlaces o directamente los datos de las entidades con las que se relaciona. O al ver que en el modelo hay entidades, y una de las entidades modela una persona, saber que para mostrar en algun lado (una lista desplegable, una grilla&amp;hellip;.) a qu&amp;eacute; persona estamos refiriendo, deber&amp;aacute; mostrar nombre, apellido, y tal vez alg&amp;uacute;n de legajo. O que si estoy armando una aplicaci&amp;oacute;n distribuida en Java, sepa deducir qu&amp;eacute; servicios web debo implementar, que DTOs hay que definir, seg&amp;uacute;n los casos de usos que est&amp;eacute;n descriptos en el modelo, y que escriba los ensambladores de esos DTOs.&lt;/p&gt;
&lt;p&gt;Esos sos ejemplos peque&amp;ntilde;os y grandes de decisiones. Pero la idea es ir avanzando en tener m&amp;aacute;s decisiones, y m&amp;aacute;s reglas, implementadas no con un r&amp;iacute;gido sistema de reglas forward chaining o backward chaining (que no lo descarto, de ah&amp;iacute; mi implementaci&amp;oacute;n de AjProlog en curso y de otras ideas), sino ir viendo de explorar la inserci&amp;oacute;n de decisiones en cualquier momento del proceso de generaci&amp;oacute;n de c&amp;oacute;digo.&lt;/p&gt;
&lt;p&gt;Otro ejemplo: en el proyecto en curso, un sistema real, se implement&amp;oacute; con AjBasic/AjGenesis una serie de reglas que examinan la base de datos de desarrollo, y detectan inconsistencias en los nombres de las columnas o relaciones de uno a muchos mal definidas. Y podemos seguir implementando m&amp;aacute;s reglas, que nos avisen de otros problemas.&lt;/p&gt;
&lt;p&gt;Por todo esto, es que no adopt&amp;eacute; un lenguaje de templates existente: AjGenesis necesitaba, desde su concepci&amp;oacute;n, un lenguaje que fuera m&amp;aacute;s que un lenguaje de templates. Esto me lo hizo ver mis primeros trabajos en el tema, en los 80, cuando implement&amp;eacute; algo parecido en C, pero con limitaciones. Y cuando le&amp;iacute; en estos a&amp;ntilde;os, el libro de &lt;a target="_blank" href="http://gendotnet.com/"&gt;Kathleen Dollard&lt;/a&gt;&amp;nbsp;&lt;a target="_blank" href="http://www.amazon.com/exec/obidos/ASIN/1590591372/qid%3D1103643269/sr%3D11-1/ref%3Dsr_11_1/104-5797382-2343919"&gt;Code Generation in Microsoft .NET&lt;/a&gt; donde ella no se animaba a implementar un lenguaje, y adoptaba uno existente, como XSLT sobre XML (mala elecci&amp;oacute;n), y luego en cada cap&amp;iacute;tulo, ten&amp;iacute;a que hacer malabares con el modelo, para poder conseguir alg&amp;uacute;n resultado, al leer eso, me decid&amp;iacute; por un lenguaje flexible.&lt;/p&gt;
&lt;p&gt;Y no tard&amp;eacute; mucho en construir el prototipo. Result&amp;oacute;, como muchas otras veces, divertido! :-)&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.facebook.com/ajlopez"&gt;http://www.facebook.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1695470" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjBasic/default.aspx">AjBasic</category></item><item><title>Generación de código, AjGenesis, y Dunga dunga a la tecnología</title><link>http://msmvps.com/blogs/lopez/archive/2009/06/14/generaci-243-n-de-c-243-digo-ajgenesis-y-dunga-dunga-a-la-tecnolog-237-a.aspx</link><pubDate>Sun, 14 Jun 2009 17:20:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1695333</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1695333</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/06/14/generaci-243-n-de-c-243-digo-ajgenesis-y-dunga-dunga-a-la-tecnolog-237-a.aspx#comments</comments><description>&lt;p&gt;En un post m&amp;iacute;o&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/08/02/sobre-la-generaci-243-n-de-c-243-digo.aspx"&gt;Sobre la generaci&amp;oacute;n de c&amp;oacute;digo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;comentaba sobre &lt;a target="_blank" href="http://ajgenesis.codeplex.com"&gt;AjGenesis&lt;/a&gt; y generaci&amp;oacute;n de c&amp;oacute;digo en general. En uno de los p&amp;aacute;rrafos declaraba:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h5&gt;Dunga dunga un ratito&lt;/h5&gt;
&lt;p&gt;De alguna forma, un generador de c&amp;oacute;digo ideal no estar&amp;aacute; atado a una tecnolog&amp;iacute;a. Siempre habr&amp;aacute; alguna &amp;quot;better mousetrap&amp;quot;, siempre alguien inventar&amp;aacute; alguna nueva forma de hacer algo, siempre habr&amp;aacute; un ruso con insomnio, o un hind&amp;uacute; sin novia, que no tiene otra cosa que hacer que crear algo nuevo, ya sea en forma de librer&amp;iacute;a, framework, patr&amp;oacute;n, o estilo arquitect&amp;oacute;nico. Un generador de c&amp;oacute;digo debe ser agn&amp;oacute;stico de la tecnolog&amp;iacute;a, de las modas, de las soluciones actuales y futuras.&lt;/p&gt;
&lt;p&gt;El generador de c&amp;oacute;digo que adoptemos, debe poder adaptarse a lo que queramos hoy y ma&amp;ntilde;ana y pasado ma&amp;ntilde;ana. La estrategia es: no importa la tecnolog&amp;iacute;a, el patr&amp;oacute;n o el framework que aparezca, nuestro generador deber&amp;aacute; aprovecharse de lo que surja. Es lo que llamo la estrategia &amp;quot;dunga dunga&amp;quot;: si aparece una nueva tecnolog&amp;iacute;a T1, le hacemos &amp;quot;dunga dunga&amp;quot; a T1, si aparece un nuevo framework PiruloStruts, adaptamos nuestras plantillas a aprovecharse de ese framework, &amp;quot;dunga dunga&amp;quot; a PiruloStruts. Es como un maestro de aikido: siempre habr&amp;aacute; alguien m&amp;aacute;s fuerte, s&amp;oacute;lo hay que utilizar la fuerza del otro, para vencerlo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Un comentador &lt;a href="http://emmanueloga.blogspot.com"&gt;Emmanuel&lt;/a&gt; escrib&amp;iacute;a:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Un resumen y secciones mas especificas ayudar&amp;iacute;an (tienes que admitir que &amp;quot;Dunga dunga un ratito&amp;quot; es un titulo sobre el cual es dif&amp;igrave;cil sacar conclusiones :).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bien, me refer&amp;iacute;a a un viejo chiste, que no encontr&amp;eacute; ahora en la web, as&amp;iacute; que tratar&amp;eacute; de transcribirlo aqu&amp;iacute;, como pueda: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Resulta que un explorador se pierde en la selva, y ya exhausto, se encuentra con una tribu de ind&amp;iacute;genas, con caras de pocos amigos. Lo rodean, el que parece el jefe, se le acerca, y le despacha:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Hombre blanco! Elige! Dunga dunga o muerte!!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;El explorador no entiende qu&amp;eacute; es eso de &amp;ldquo;dunga dunga&amp;rdquo;, as&amp;iacute; que acepta eso, antes que la muerte. Los miembros de la tribu sonr&amp;iacute;en, y le empiezan a dar al pobre explorador, de formas que &amp;eacute;ste no se lo imaginaba&amp;hellip; &lt;/p&gt;
&lt;p&gt;Lo dejan, y el explorador, maltrecho, sigue su camino, se encuentra con otra tribu, otro jefe, y la ya cl&amp;aacute;sica frase:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Hombre blanco! Elige! Dunga dunga o muerte!!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;El explorador, escarmentado, responde:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;No!! No dunga dunga de nuevo!! no!!! Prefiero la muerte!!&amp;rdquo;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;El jefe asiente, pero se le acerca, le pasa brazo por el hombre, y con afecto y sonriendo, le dice:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Bueno, muerte, pero antes&amp;hellip; dunga dunga un ratito, eh?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;:-) :-)&lt;/p&gt;
&lt;p&gt;A eso me refer&amp;iacute;a cuando escrib&amp;iacute; ese post. AjGenesis, como generador de c&amp;oacute;digo, no est&amp;aacute; especializado en producir artefactos para una tecnolog&amp;iacute;a. No es como Xdoclet que s&amp;oacute;lo produce Java, o est&amp;aacute; muy orientado (por lo menos en sus comienzos) a EJB (Enterprise Java Beans).&lt;/p&gt;
&lt;p&gt;No, lo que hace AjGenesis, es aprovecharse del conocimiento del programador o equipo de programaci&amp;oacute;n, de las tecnolog&amp;iacute;as, frameworks existentes o futuros, y generar gran parte de una soluci&amp;oacute;n (o por lo menos la parte repetitiva).&lt;/p&gt;
&lt;p&gt;Recordemos que AjGenesis puede partir de un modelo abstracto y generar artefactos de textos (que pueden ser una soluci&amp;oacute;n completa):&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesis30.png" alt="" /&gt;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Notemos que puede haber m&amp;aacute;s de un modelo inicial. En muchos de los ejemplos que publiqu&amp;eacute;, hay un modelo independiente de la plataforma (por ejemplo, que describe que nuestro sistemas tendr&amp;aacute; departamentos, empleados, clientes, proveedores&amp;hellip;) y un modelo de tecnolog&amp;iacute;a (que indica que vamos a usar tal base de datos, y tal lenguaje, y una interface web, etc..)&lt;/p&gt;
&lt;p&gt;Pero tambi&amp;eacute;n puede partir de la base de datos, y generar un modelo de base, que puede ser completado, ajustado, y usado m&amp;aacute;s adelante la generaci&amp;oacute;n de c&amp;oacute;digo:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesis31.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El modelo a usar es totalmente definible. Y las tareas y plantillas a usar, totalmente definibles. Si lo que Uds. necesitan, es generar aplicaciones con interfaz web, usando Struts 2, es cuesti&amp;oacute;n de armarse las plantillas y tareas que generen ese tipo de soluci&amp;oacute;n. Si luego necesitan generar una aplicaci&amp;oacute;n en ASP.NET 3.5, con persistencia resuelta en NHibernate, de nuevo es cuesti&amp;oacute;n de definir las tareas y plantillas adecuadas.&lt;/p&gt;
&lt;p&gt;Pero si el d&amp;iacute;a de ma&amp;ntilde;ana, aparece un nuevo ORM (Object Relational Mapper), o hay una nueva forma de implementar la persistencia, podemos &amp;ldquo;instruir&amp;rdquo; al AjGenesis para que genere los artefactos de textos que necesitemos.&lt;/p&gt;
&lt;p&gt;Ya he publicado ejemplos, explicaciones de todo esto en&lt;/p&gt;
&lt;p&gt;&lt;a target="_blank" href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx"&gt;Posts sobre AjGenesis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;desde una explicaci&amp;oacute;n de Hola Mundo:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2006/11/19/generando-c-digo-hello-world-con-ajgenesis.aspx" title="Generando C&amp;oacute;digo- Hello World con AjGenesis"&gt;Generando C&amp;oacute;digo- Hello World con AjGenesis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;hasta aplicaciones completas en distintas tecnolog&amp;iacute;as:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/06/25/generando-aplicaciones-con-ajgenesis.aspx" title="Generando aplicaciones con AjGenesis"&gt;Generando aplicaciones con AjGenesis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En esos ejemplos, el modelo se define en archivos XML, pero tambi&amp;eacute;n pueden tomarlo desde texto:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/09/29/modelo-textual-para-generaci-243-n-de-c-243-digo-con-ajgenesis.aspx" title="Modelo textual para generaci&amp;oacute;n de c&amp;oacute;digo con AjGenesis"&gt;Modelo textual para generaci&amp;oacute;n de c&amp;oacute;digo con AjGenesis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;y desde otras fuentes menos convencionales:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/11/25/ajgenesis-modelo-desde-la-base-de-datos.aspx" title="AjGenesis- Modelo desde la Base de Datos"&gt;AjGenesis- Modelo desde la Base de Datos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2007/11/27/ajgenesis-modelo-generado-desde-los-assemblies.aspx" title="AjGenesis- Modelo generado desde los assemblies"&gt;AjGenesis- Modelo generado desde los assemblies&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Si hasta pueden implementar una soluci&amp;oacute;n web que genere c&amp;oacute;digo para cualquiera que lo necesite:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/04/03/code-generation-as-a-service.aspx" title="Code Generation as a Service"&gt;Code Generation as a Service&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As&amp;iacute; que no tienen excusas: no pueden quejarse de que no les avis&amp;eacute;, o que me encanut&amp;eacute;, ocult&amp;eacute; algo bajo la manga. Tienen todo eso disponible desde hace a&amp;ntilde;os. S&amp;oacute;lo falta poner cabeza y cerebro, en descubrir los modelos de base que necesitamos, y escribir las tareas y plantillas. Recomiendo siempre partir de una aplicaci&amp;oacute;n de ejemplo, que resuelva lo que Uds. necesitan, usando la tecnolog&amp;iacute;a que hayan elegido, y desde ah&amp;iacute;, ir construyendo las tareas y plantillas que necesiten.&lt;/p&gt;
&lt;p&gt;Como siempre aclaro, no toda la aplicaci&amp;oacute;n puede crearse por generaci&amp;oacute;n de c&amp;oacute;digo. Pero se pueden aplicar t&amp;eacute;cnicas, como generar desde el modelo que elijamos, s&amp;oacute;lo algunos artefactos de texto, y otros, los generamos manualmente.&lt;/p&gt;
&lt;p&gt;Lo interesante, es que as&amp;iacute;, cuando pasen las tecnolog&amp;iacute;as, cuando aparecen nuevas, podemos reaprovechar nuestro conocimiento anterior, al haber definido un modelo que describa nuestro problema, y luego, al conocer una nueva tecnolog&amp;iacute;a, y c&amp;oacute;mo resolver los mismos problemas de otra forma, podemos generar c&amp;oacute;digo para la nueva forma de hacer las cosas.&lt;/p&gt;
&lt;p&gt;Yendo a un ejemplo concreto. Desde hace d&amp;eacute;cadas, estamos haciendo ABM (Altas, Bajas y Modificaciones) de valores, como pa&amp;iacute;ses, provincias y dem&amp;aacute;s. Cuando resolvimos eso en Visual Fox, un cliente nos pidi&amp;oacute; hacerlo en ASP cl&amp;aacute;sico. Cuando resolvimos eso en ASP cl&amp;aacute;sico, otro cliente nos pidi&amp;oacute; eso en ASP.NET, o en JSP o en JSF (JavaServer Faces) o en lo que aparezca ma&amp;ntilde;ana. Pero el problema a resolver es el mismo: mantener una lista de valores. Si luego cambia la tecnolog&amp;iacute;a, cambia la soluci&amp;oacute;n a aplicar, pero el problema inicial se mantiene. En AjGenesis, podemos definir un modelo independiente&amp;nbsp; de la tecnolog&amp;iacute;a (por ejemplo, definiendo las entidades que tenemos que manejar, como Cliente, Factura, Remito, etc&amp;hellip; y sus relaciones), y por otro, instruyendo sobre qu&amp;eacute; tecnolog&amp;iacute;a usar (aportando uno o varios modelos dependientes de la tecnolog&amp;iacute;a), como ASP.NET, ASP.NET MVC, WCF, JSP, JSF, Struts 1 o 2, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;Otro camino hubiera sido lo que muchos de nosotros encaramos: hacer nuestro propio framework. He visto muchas consultoras de software, &amp;ldquo;casarse&amp;rdquo; con una tecnolog&amp;iacute;a (ej. Visual Fox), estudiarla, armar un framework sobre ella (que resuelva los problemas cl&amp;aacute;sicos, como ABMs, seguridad, autorizaci&amp;oacute;n, validaciones, etc&amp;hellip;) y luego ver c&amp;oacute;mo, ese trabajo de a&amp;ntilde;os, se diluye, porque la tecnolog&amp;iacute;a cambia.&lt;/p&gt;
&lt;p&gt;Si nosotros elevamos el nivel de abstracci&amp;oacute;n, identificamos los problemas a resolver (ABMs, listas, buscadores, seguridad, procesos, validaciones, reglas de negocio), y luego los resolvemos en una tecnolog&amp;iacute;a (ya sea viendo c&amp;oacute;digo de ejemplo, armando nuestros propios ejemplos, et&amp;hellip;), podemos describir ese mapeo de problema a soluci&amp;oacute;n concreta, usando las tareas y plantillas de AjGenesis.&lt;/p&gt;
&lt;p&gt;Como ejemplo: cuando comenc&amp;eacute; con el proyecto, no exist&amp;iacute;a ASP.NET 2.x. Sin embargo, los modelos que constru&amp;iacute; como ejemplos de base, pudieron ser usados para luego generar aplicaciones de ASP.NET 2.x. Actualmente, en un proyecto, estamos adaptando conocimiento previo, para generar c&amp;oacute;digo sobre .NET y &lt;a target="_blank" href="http://www.oakleafsd.com/pgProducts_mmnet.htm"&gt;Mere Mortals Framework&lt;/a&gt;. Y el modelo que construimos, f&amp;aacute;cilmente podr&amp;iacute;a ser reusado para otras aplicaciones, y otras tecnolog&amp;iacute;as,como Clipper o COBOL, hasta ASP.NET MVC o Wicket. El construir el modelo, pone de manifiesto qu&amp;eacute; es lo que queremos resolver, los problemas b&amp;aacute;sicos, que terminan expres&amp;aacute;ndose de forma independiente de la tecnolog&amp;iacute;a de moda, o el framework popular del momento.&lt;/p&gt;
&lt;p&gt;Y aunque usemos una sola tecnolog&amp;iacute;a, el ejercicio de definir el modelo, definir las tareas y plantillas, aporta una clara separaci&amp;oacute;n entre lo abstracto, y lo que llamo las &amp;ldquo;technicalities&amp;rdquo;, los detalles t&amp;eacute;cnicos de implementaci&amp;oacute;n, que el d&amp;iacute;a de ma&amp;ntilde;ana pueden cambiar.&lt;/p&gt;
&lt;p&gt;Entonces, no importa la tecnolog&amp;iacute;a: AjGenesis le puede hacer dunga dunga a la tecnolog&amp;iacute;a que venga. Si Uds. creen que la tecnolog&amp;iacute;a que Uds. usan actualmente, va a durar para siempre, lamento desilusionarlos. Vean la historia de la programaci&amp;oacute;n, los &amp;uacute;ltimos 30 o 50 a&amp;ntilde;os, y ver&amp;aacute;n que lo &amp;uacute;nico permanente es el cambio.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.facebook.com/ajlopez" title="http://www.facebook.com/ajlopez"&gt;http://www.facebook.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1695333" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Java/default.aspx">Java</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>AjGenesisCF: generación de código para generation for .NET Compact Framework</title><link>http://msmvps.com/blogs/lopez/archive/2009/05/29/ajgenesiscf_2D00_code_2D00_generation_2D00_for_2D00_net_2D00_compact_2D00_framework.aspx</link><pubDate>Fri, 29 May 2009 05:09:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1693389</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1693389</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/05/29/ajgenesiscf_2D00_code_2D00_generation_2D00_for_2D00_net_2D00_compact_2D00_framework.aspx#comments</comments><description>&lt;p&gt;Gracias al trabajo de &lt;a target="_blank" href="http://blogs.southworks.net/fboerr/"&gt;Federico Boerr&lt;/a&gt; y su equipo, tenemos una nueva versi&amp;oacute;n de &lt;a target="_blank" href="http://www.ajlopez.com/ajgenesis"&gt;AjGenesis&lt;/a&gt;, escrita para ejecutarse desde .NET Compact Framework:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ajgenesiscf.codeplex.com/" title="http://ajgenesiscf.codeplex.com/"&gt;http://ajgenesiscf.codeplex.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajgenesiscf.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Esta versi&amp;oacute;n s&amp;oacute;lo usa las caracter&amp;iacute;sticas soportadas por el Compact Framework. Entonces, no tenemos todas las del proyecto original. Por ejemplo, s&amp;oacute;lo usa las caracter&amp;iacute;sticas de reflections soportadas por CF, una de las que queda fuera es la capacidad de crear una instancia con pasando par&amp;aacute;metros en el constructor. Pero podemos compilar AjGenesis como .DLL, e invocarla desde un programa nuestro, usar templates, tareas y AjBasic. El c&amp;oacute;digo publicado por Federico contiene un programa de uso de ejemplo.&lt;/p&gt;
&lt;p&gt;M&amp;aacute;s informaci&amp;oacute;n sobre el proyecto original:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ajgenesis.codeplex.com"&gt;http://ajgenesis.codeplex.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/category/ajgenesis/"&gt;http://ajlopez.wordpress.com/category/ajgenesis/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1693389" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Modelo, decisiones, inteligencia artificial y AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2009/03/22/modelo-decisiones-inteligencia-artificial-y-ajgenesis.aspx</link><pubDate>Sun, 22 Mar 2009 20:28:16 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1680480</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1680480</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/03/22/modelo-decisiones-inteligencia-artificial-y-ajgenesis.aspx#comments</comments><description>&lt;p&gt;En el recientemente creado grupo de Google AltNet-Argentina, el bueno de Fabio Maulo planteó una pregunta en el thead:&lt;/p&gt; &lt;p&gt;&lt;a href="http://groups.google.com/group/altnet-argentina/t/6668697a12cc04aa" target="_blank"&gt;ORuM&lt;/a&gt;&lt;/p&gt; &lt;p&gt;donde escribía&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;a&gt;&lt;/a&gt;Quien me conoce un poco, o me ha leido en algún lado, conoce ya la acronimo &lt;br /&gt;ORuM.La realida es que nunca tuve la ocasión de una buena confrontación &lt;br /&gt;sobre el tema.  &lt;p&gt;Para titular la mesa sería: &lt;br /&gt;Object Relational unMapping &lt;br /&gt;Mas allá del ORM. &lt;/p&gt;&lt;/blockquote&gt; &lt;blockquote&gt; &lt;p&gt;Quisiera compartir, confrontar, ampliar algunas ideas y verificar la &lt;br /&gt;factibilidad. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;La idea es tener en claro, cómo se toman algunas decisiones, en el caso de tener un dominio de clases, y llegar al mapeo de en una base de datos, no preexistente. Es un caso tipo, como escribía el propio Maulo: &lt;blockquote&gt; &lt;p&gt;Yo quisiera llegar a : &amp;quot;che, yo tengo este dominio que tendría que persistir en ORACLE, fijate vos! a mi lo que me interesa es que persista.&amp;quot; &lt;p&gt;El DSL sería: &lt;p&gt;Che.Tengo(&amp;quot;MiDominio.dll&amp;quot;).Que.TieneQuePersistirEn(&amp;quot;ORACLE&amp;quot;).FijateVos();&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Para mí, esto es parecido a lo que trato muchas veces de resolver con &lt;a href="http://www.codeplex.com/ajlopez" target="_blank"&gt;AjGenesis&lt;/a&gt;: &lt;p&gt;&amp;quot;Tengo X quiero resolverlo con Y&amp;quot;, donde X puede ser un dominio de entidades, un dominio más tipo DDD, una lista de servicios, lo que sea, e Y sería JSP, Struts2, JSF, ASP.NET MVC, NHibernate, Hibernate, MySql, SQL Server, y demás. Es lo mismo que hace un programador: toma decisiones, ante lo que tiene que hacer. &lt;p&gt;Es por eso que en AjGenesis tomé algunas decisiones tempranas, para poder ir avanzando en un camino, que menciono en: &lt;p&gt;&lt;a title="Sobre la generaci&amp;oacute;n de c&amp;oacute;digo" href="http://msmvps.com/blogs/lopez/archive/2007/08/02/sobre-la-generaci-243-n-de-c-243-digo.aspx"&gt;Sobre la generación de código&lt;/a&gt; &lt;blockquote&gt; &lt;p&gt;... el modelo a usar ... PUEDE SER GENERADO por el propio sistema, &lt;strong&gt;más un sistema experto.&lt;/strong&gt; No imagino una aplicación más inmediata de la &amp;quot;inteligencia artificial&amp;quot;. Imagino agentes inteligentes, que colaboren en una red compartida, cada uno generando parte del modelo, cada uno consumiendo algo que otro produce, y colaborando, para generar un sistema... Sí, ya sé, tengo que tomar la píldora verde, en lugar de la roja... ;-)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Esa es una de las razones de tener en AjGenesis: &lt;p&gt;-&amp;nbsp;un modelo&lt;br /&gt;-&amp;nbsp;más que sólo un lenguaje de templates&lt;br /&gt;-&amp;nbsp;aplicar el lenguaje en tasks, que modifican y completan el modelo &lt;p&gt;Si sólo tuviera templates, sólo haría transformaciones X -&amp;gt; Z, de una forma, digamos, lineal, desde, para poner un ejemplo, una clase o un modelo que describe una clase, a un código o archivo de configuración de persistencia. &lt;p&gt;A lo que voy, es que el camino que quiero para AjGenesis, en algún momento (no para que todos lo usen así), es que sea un sistema experto, que tome decisiones. De ahí que, desde el principio: &lt;p&gt;- tenga un lenguaje completo, con toma de decisiones, que pueden ser complejas&lt;br /&gt;- tiene acceso al framework de .NET, para poder ser extendido de cualquier manera.&lt;br /&gt;- invoque a tareas, no simplemente a transformar el modelo X usando el template T &lt;p&gt;Eso explica también, algunos caminos que estoy explorando, como &lt;a href="http://code.google.com/p/ajlisp/" target="_blank"&gt;AjLisp&lt;/a&gt;, y &lt;a href="http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjProlog-0.3" target="_blank"&gt;AjProlog&lt;/a&gt; (aunque son más para entrenarme, que para aplicarlos directamente en AjGenesis). Habrá que investigar si este camino es posible, pero me parece que está relacionado con el tema planteado en el grupo. Veamos, volvamos al problema inicial. &lt;h3&gt;De clases a persistencia&lt;/h3&gt; &lt;p&gt;Las opciones de mapeo que podemos considerar, son las mostradas por el bueno de &lt;a href="http://www.martinfowler.com" target="_blank"&gt;Martin Fowler&lt;/a&gt;: &lt;p&gt;&lt;a href="http://martinfowler.com/eaaCatalog/singleTableInheritance.html" target="_blank"&gt;Single Table Inheritance&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://martinfowler.com/eaaCatalog/classTableInheritance.html" target="_blank"&gt;Class Table Inheritance&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://martinfowler.com/eaaCatalog/concreteTableInheritance.html" target="_blank"&gt;Concrete Table Inheritance&lt;/a&gt;&lt;/p&gt; &lt;p&gt;En una situación ideal (no costo en tiempo de queries o de update, sin limite de memoria en disco), todo seria igual. &lt;p&gt;Como la situación no es ideal, me imagino que los costos de cada decisión se mediran en: &lt;p&gt;- Rendimiento de actualización y consulta &lt;p&gt;- Espacio de almacenamiento &lt;p&gt;A primera vista, me imagino que el primer punto es el mas peliagudo. &lt;p&gt;Para concretar, tomemos un modelo sencillo. Sea clase Empresa, subclases Cliente, Proveedor. &lt;p&gt;Habría que ver qué consecuencias tiene entonces, el tener una tabla empresas, con un campo discriminador de si es cliente o proveedor. ¿Qué pasa si hay muchos campos en comun? ¿O si hay muchos campos de diferencia? Pienso que mas va a influir el tema: ¿pero queda ahí el dominio? Si el día de mañana aparecen más subclases, ClienteExtranjero, ProveedorExterno,&amp;nbsp;¿no se complicará el haber adoptado una sola tabla? &lt;p&gt;Si ponemos tablas Empresa (con los datos comunes), Clientes (con los datos adicionales), Proveedor (con los datos adicionales), habrá que hilar fino en las consultas. No sólo está el tema del rendimiento de actualización y consulta. Tambien esta&amp;nbsp;la frecuencia de algunas operaciones. Es decir, si una consulta determinada tarda X tiempo, habrá que ponderarla tambien por la frecuencia de esa consulta en la operación normal del sistema. &lt;p&gt;Con tablas Clientes, Proveedores, habra que comprobar que la actualizacion sea mas rapida que en el anterior caso. Y vigilar que pasa, y con cuanta frecuencia, se necesita una consulta sobre Empresas (que imagino debera implicar un UNION). &lt;p&gt;Entonces, no sólo es el modelo de clases, sino cómo se usa, lo que puede influir en cómo hagamos el mapeo. &lt;p&gt;ESTO ES LO QUE YO VEO EN MUCHOS MODELOS ya existentes, que no tienen todo LO QUE SE NECESITA DE UN MODELO. Un modelo de clases se queda corto, para tomar algunas decisiones. Lo mismo, si partimos desde una base ya diseñada. Partir de esos modelos, implica que en algún momento lo tenemos que enriquecer, con anotaciones en el modelo de clases, o agregando información en metadata o en algún momento, si partimos desde la base de datos. &lt;p&gt;Partir de un modelo de clases o de la base de datos, tiene la ventaja de partir de algo conocido. Pero para muchas de las operaciones que quisiéramos hacer (en este caso &amp;quot;simple&amp;quot;, mapeo a relacional, imaginen otros casos como servicios distribuidos, seguridad, cache en el cliente, etc.), hace falta más información de contexto. &lt;p&gt;De ahí, que yo esté a favor de un modelo distinto, más enriquecido. &lt;h3&gt;De Aristóteles a Kant&lt;/h3&gt; &lt;p&gt;En los noventa, en una revista Byte, leí una breve reseña, sobre gente que estaba armando algo que lo llamaban KANT. En honor a las categorías del filósofo alemán (yo diría que se referían más a categorías de Aristóteles), ellos planteaban que todo en, lo que hoy llamaríamos, modelo, está incluído en alguna categoría como: &lt;p&gt;- Persona&lt;br /&gt;- Organización&lt;br /&gt;- Bien Físico&lt;br /&gt;- Lugar Físico&lt;br /&gt;- Documento&lt;br /&gt;- Suceso&lt;br /&gt;- Lapso &lt;p&gt;y demás. Por ejemplo, un Empleado entraría en la categoría Persona, un Cliente o Proveedor, en la categoría Organización. El que un Empleado estuviera contratado por una Empresa, era un Lapso (un intervalo, posiblemente abierto, de tiempo) establecido entre una Persona y una Organización. A partir de las categorías, se podía inferir que toda Persona tiene fecha de nacimiento, y otros atributos, que un Lapso puede tener tiempo de inicio y tiempo de final. (Escribo sin tener la referencia, de memoria). &lt;p&gt;Esa reseña siempre influyó en lo que quiero hacer con un modelo rico, abstracto. Sirve para poner más semántica sobre lo que estamos describiendo, más de lo que daría un modelo de código o de base de datos. Sigo pensando que algo así debe ser el modelo del que partir, en la generación de código o en otras ideas. &lt;p&gt;Apenas una punta de eso (el tener categorías llamadas prototipos, que sirvan de base para generar un modelo simple), está desde hace tiempo en &lt;a href="http://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=ajgenesis&amp;amp;ReleaseId=7261" target="_blank"&gt;AjExamplesExamples3.zip&lt;/a&gt;, en el directorio Prototypes, y Seeds. Es una idea con implementación mínima, a explicar en detalle en otro post. &lt;p&gt;Nos leemos! &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;br /&gt;En estos días, revival de los 80s en mi vida &lt;a title="http://www.youtube.com/watch?v=dgwmErO_nlQ" href="http://www.youtube.com/watch?v=dgwmErO_nlQ"&gt;http://www.youtube.com/watch?v=dgwmErO_nlQ&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1680480" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Inteligencia+Artificial/default.aspx">Inteligencia Artificial</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Máquinas de Estado en C# 3.0 usando AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2008/10/21/m-225-quinas-de-estado-en-c-3-0-usando-ajgenesis.aspx</link><pubDate>Tue, 21 Oct 2008 09:39:39 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1651489</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1651489</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/10/21/m-225-quinas-de-estado-en-c-3-0-usando-ajgenesis.aspx#comments</comments><description>&lt;p&gt;Recientemente encontré el trabajo de &lt;a title="Andrew Matthews" href="http://aabs.wordpress.com/"&gt;Andrew Matthews&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;a title="Permanent Link to State Machines in C# 3.0 using T4 Templates" href="http://aabs.wordpress.com/2008/06/26/state-machines-in-c-30-using-t4-templates/"&gt;Permanent Link to State Machines in C# 3.0 using T4 Templates&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Tomé el ejemplo y lo reimplementé usando mi proyecto de generación de código &lt;a href="http://www.ajlopez.com/ajgenesis" target="_blank"&gt;AjGenesis&lt;/a&gt;. Para correr este ejemplo, tenemos que bajar la última versión publicada 0.5 desde &lt;a href="http://www.codeplex.com/ajgenesis"&gt;la página del proyecto en Codeplex&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;(más información sobre el proyecto, ejemplos, explicación del funcionamiento en &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx" target="_blank"&gt;mis anteriores posts&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;Pueden bajar &lt;a href="http://www.ajlopez.com/downloads/AjGenesisStateMachine.zip" target="_blank"&gt;el código de este ejemplo&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;El modelo que usé es el mismo del post original de Andrew:&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:31d7985f-401f-4174-b268-899b991b3aa3" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;width:493px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;?&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;StateModels&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;StateModel &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;My&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; start&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;States&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;State &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon1&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon1&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;State &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon2&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;State &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon3&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon3&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;States&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Inputs&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Input &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;diplomaticIncident&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;diplomaticIncident&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Input &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;assassination&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;assassination&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Input &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;ID&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;coup&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;coup&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Inputs&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Transitions&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Transition &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;from&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon1&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; to&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; on&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;diplomaticIncident&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Transition &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;from&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon2&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; to&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon3&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; on&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;assassination&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
      &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Transition &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;from&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon3&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; to&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;defcon1&amp;quot;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt; on&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;coup&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Transitions&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
  &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;StateModel&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;StateModels&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;(Andrew escribió que ha sido influido un poco por la serie de TV 24, al elegir los estados del ejemplo... ;-)&lt;/p&gt;
&lt;p&gt;Modifiqué la solución original:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesisstates.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Ahora, hay un archivo &lt;strong&gt;Model.xml&lt;/strong&gt; que contiene el modelo de arriba. El archivo &lt;strong&gt;MyStateModel.cs&lt;/strong&gt;&amp;nbsp;es automáticamente generado desde el modelo. Cambié la solución para tener un evento de Pre-Build en el proyecto &lt;strong&gt;TestHarness&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;$(ProjectDir)..\VsMakeStates.cmd&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;El archivo .cmd contiene:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;cd ..\..\..&lt;br /&gt;c:\ajlopez\ProyectosNet2\AjGenesis-0.5\bin\AjGenesis.Console TestHarness\Model.xml GenStates.ajg &lt;/font&gt;
&lt;p&gt;(&lt;strong&gt;TENEMOS&lt;/strong&gt; que cambiar la segunda línea para apuntar al directorio binario de AjGenesis 0.5)&lt;/p&gt;
&lt;p&gt;Con este comando, &lt;strong&gt;AjGenesis.Console&lt;/strong&gt; carga el modelo desde el archivo .xml, y aplica una tarea, &lt;strong&gt;GenStates.ajg&lt;/strong&gt;, escrita enwritten in AjBasic:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;for each StateModel in StateModels&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TransformerManager.Transform(&amp;quot;State.tpl&amp;quot;,&amp;quot;TestHarness\${StateModel.ID}StateModel.cs&amp;quot;,Environment)&lt;br /&gt;end for&lt;/font&gt; 
&lt;p&gt;Hay otro comando, que podemos lanzar directamente desde la línea de comando, &lt;strong&gt;MakeStates.cmd&lt;/strong&gt;, conteniendo: 
&lt;p&gt;c:\ajlopez\ProyectosNet2\AjGenesis-0.5\bin\AjGenesis.Console TestHarness\Model.xml GenStates.ajg 
&lt;p&gt;Amo mi template AjBasic&amp;nbsp;en &lt;strong&gt;GenStates.ajg&lt;/strong&gt; ;-) un fragmento: 
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:1fdd4534-69ad-4611-9250-57e321cf751f" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; System.Collections.Generic;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; Aabs;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;using&lt;/span&gt;&lt;span style="color:#000000;"&gt; Core;

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;namespace&lt;/span&gt;&lt;span style="color:#000000;"&gt; ${StateModel.ID} {
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;enum&lt;/span&gt;&lt;span style="color:#000000;"&gt; ${StateModel.ID}States : &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;int&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    {
&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;#
    sep &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt; each State &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;in&lt;/span&gt;&lt;span style="color:#000000;"&gt; StateModel.States
#&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        ${sep}${State.ID}        &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt; ${State.name}&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;#
        sep &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;,&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    end &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;for&lt;/span&gt;&lt;span style="color:#000000;"&gt;
#&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    } &lt;/span&gt;&lt;span style="color:#008000;"&gt;//&lt;/span&gt;&lt;span style="color:#008000;"&gt; end enum ${StateModel.Id}States&lt;/span&gt;&lt;span style="color:#008000;"&gt;
&lt;/span&gt;&lt;span style="color:#000000;"&gt;
...
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Está basado en archivo .tt de Andrew Matthews. Notemos que no hay&amp;nbsp;referencia a nodos .XML o similares. AjGenesis carga el modelo en memoria, como un objeto dinámico. El lenguaje AjBasic puede acceder al modelo, usándolo como un&amp;nbsp;objecto cualquiera. El uso de &lt;strong&gt;${ }&lt;/strong&gt;&amp;nbsp;reemplaza la salida con algún valor, tomado de las variables o del modelo en proceso.&lt;/p&gt;
&lt;p&gt;El principal punto en este ejemplo es que está basado en un modelo libre (AjGenesis puede cargar cualquier modelo, no se usa uno predefinido). Si uno quiere agregar más información, podemos escribir más atributos, elementos, en el archivo .xml. Y usarlos desde el código de template. No hay un esquema fijo.&lt;/p&gt;
&lt;p&gt;Otro punto a destacar: el ejemplo podría ser modificado para generar la solución Visual Studio completa, o para generar una solución en otro lenguaje (un ejemplo generando una solución VS completa:&lt;br /&gt;&lt;a title="Code Generation for LINQ and C# 3.0 with AjGenesis" href="http://ajlopez.wordpress.com/2008/09/30/code-generation-for-linq-and-c-30-with-ajgenesis/"&gt;Code Generation for LINQ and C# 3.0 with AjGenesis&lt;/a&gt;&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;Gracias a Andrés por un ejemplo tan interesante. Pueden leer más sobre su implementación en el post mencionado:&lt;/p&gt;
&lt;p&gt;&lt;a title="Permanent Link to State Machines in C# 3.0 using T4 Templates" href="http://aabs.wordpress.com/2008/06/26/state-machines-in-c-30-using-t4-templates/"&gt;Permanent Link to State Machines in C# 3.0 using T4 Templates&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1651489" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Otro modelo para AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2008/10/03/otro-modelo-para-ajgenesis.aspx</link><pubDate>Fri, 03 Oct 2008 11:07:12 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1649592</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1649592</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/10/03/otro-modelo-para-ajgenesis.aspx#comments</comments><description>&lt;p&gt;En este post voy a describir una idea, no hay implementacion todavía. &lt;a href="http://www.ajlopez.com/ajgenesis" target="_blank"&gt;AjGenesis&lt;/a&gt;, mi proyecto de código abierto de generación de código, está basado en modelos, tareas y plantillas. Cada artecfacto a ser usado, podemos definirlo nosotros, y así se consigue generar salidas, archivos, código para cualquier tecnología, framework o plataforma.&lt;/p&gt; &lt;p&gt;El modelo reside en memoria, durante su proceso. Podemos cargar en memoria varios modelos a la vez: en los ejemplos que he publicado, un modelo abstracto describe la solución en términos generales, y otro modelo de tecnología define el lenguaje, base de datos, patrones, que se usaran en el proceso de generación de código.&lt;/p&gt; &lt;p&gt;Ambos modelos pueden ser cargados desde archivos XML, o desde archivos de texto (esta es una nueva característica, todavía en prueba). Ahora, quisiera proponer otro camino: modelos en planillas de cálculo.&lt;/p&gt; &lt;h3&gt;El ejemplo&lt;/h3&gt; &lt;p&gt;En un post reciente:&lt;/p&gt; &lt;p&gt;&lt;a title="Modelo textual para generaci&amp;oacute;n de c&amp;oacute;digo con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2008/09/29/modelo-textual-para-generaci-243-n-de-c-243-digo-con-ajgenesis.aspx"&gt;Modelo textual para generación de código con AjGenesis&lt;/a&gt;&lt;br /&gt;&lt;a title="Textual model for code generation in AjGenesis" href="http://ajlopez.wordpress.com/2008/09/28/textual-model-for-code-generation-in-ajgenesis/"&gt;Textual model for code generation in AjGenesis&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Presenté ahí un modelo simple, en dos representaciones: XML y textual. Ese modelo podría ser expresado en una planilla Excel, como:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesismodel1.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;El alcance de una descripción de objeto está determinada por la indentación: Entity Customer es un elemento de Entities (vean que no importa dejar filas en blanco). Podemos usar una tabla para describir un elemento compuesto de varios. Una propiedad simple puede ser descripta en dos columnas consecutivas: la primera conteniendo el nombre de la propiedad, la segunda nos da el valor. Si queremos describir un objeto en otra&amp;nbsp;hola de la misma planilla,&amp;nbsp;ponemos el nombre entre corchetes [...], como en &amp;quot;Entity [Employee]&amp;quot;, que nos podría llevar a otra hoja como:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajgenesismodel2.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;El principal beneficio de este modelo es la clara representación que conseguimos. Colores y tipos de letras mejoran la presentación, pero son ignorados en la carga del modelo. Pero la presentación se mejora.&amp;nbsp;Como siempre digo, no somos vulcanos (al Sr. Spock le bastaría un archivo XML), y una buena presentación nos ayuda a procesar información.&lt;/p&gt; &lt;h3&gt;Próximos pasos&lt;/h3&gt; &lt;p&gt;Si consideran que esta propuesta es útil, podría escribir un nuevo Object Builder que se alimente de archivos Excel, para cargar un modelo. Debería elegir la librería a usar: podría tomar el modelo de objetos de Excel, aunque eso implica que para usarlo, se deba tener el Excel instalado. Como siempre, sugerencias, comentarios, bienvenidos!&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1649592" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Generación de código para LINQ y C# 3.0 con AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2008/10/01/generaci-243-n-de-c-243-digo-para-linq-y-c-3-0-con-ajgenesis.aspx</link><pubDate>Wed, 01 Oct 2008 10:51:18 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1649363</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1649363</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/10/01/generaci-243-n-de-c-243-digo-para-linq-y-c-3-0-con-ajgenesis.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://www.ajlopez.com/ajgenesi" target="_blank"&gt;AjGenesis&lt;/a&gt;, mi proyecto open source de generación de código, usa un modelo definido por el usuario. Podemos definir tareas y templates, para transformar el modelo a código y archivos de texto. Podemos escribir nuestro propio modelo, agregar tareas y transformaciones. Desde una tarea, se puede invocar a objetos .NET o código AjBasic, en el medio del proceso de generación. Es un proceso flexible: genera lo que Ud. quiera generar, no tiene un patrón predeterminado.&lt;/p&gt; &lt;p&gt;Como el modelo lo define uno, el sistema no está limitado a un tipo de proyecto. Al estar basado en templates y tareas definidas, genera artefactos de código que no están ligados una sola tecnología. Podmos generar archivos para cualquier tecnología, framework, línea de negocios y plataforma. Podemos generar scripts de DDL, o una aplicación completa de base, o cualquier cosa en el medio. Es nuestra decisión hasta donde llegar.&lt;/p&gt; &lt;p&gt;Cuando comencé a escribir y usar el sistema, no existía .NET 2.0. Cuando la nueva tecnología se hizo pública, escribí tareas y templates adicionas para aprovechar las nuevas características como master pages, themes y nuevos controles ASP.NET, sin necesidad de tocar el código núcleo de AjGenesis. Una vez los nuevos templates y tareas estuvieron escritos, pude generar aplicaciones ASP.NET 2.x, a partir de los mismos modelos que ya tenía armados para mis otros cursos y trabajos.&lt;/p&gt; &lt;p&gt;Ahora, como una prueba de concepto, escribí un nuevo ejemplo, que genera código usando LINQ, en nuevo chico en el barrio de .NET 3.x. El resultado fue publicado como AjGenesisExamplesNet3.zip en la página de&amp;nbsp;&amp;nbsp;&lt;a href="http://www.codeplex.com/ajgenesis/Release/ProjectReleases.aspx?ReleaseId=7261" target="_blank"&gt;ejemplos de AjGenesis en CodePlex&lt;/a&gt;. Para ejecutar el ejemplo, necesitamos la&amp;nbsp;&lt;a href="http://www.codeplex.com/ajgenesis/Release/ProjectReleases.aspx?ReleaseId=7262" target="_blank"&gt;actual versión 0.5&lt;/a&gt;&amp;nbsp;(incluye código fuente, ejemplos iniciales, y binarios). (Hay una versión 0.5.1 en desarrollo que pueden ir viendo en &lt;a href="http://www.codeplex.com/ajgenesis/SourceControl/ListDownloadableCommits.aspx" target="_blank"&gt;el repositorio de código del proyecto&lt;/a&gt;).&lt;/p&gt; &lt;h3&gt;El ejemplo&lt;/h3&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.todocontenidos.com/images/articles/ajgenesisnet3dir.png" alt="" /&gt;&lt;/p&gt; &lt;p&gt;Hay sólo un modelo en el ejemplo: AjFirstExample, con un simple modelo XML describiendo a dos entidades planas, Customers y Suppliers. Es el mismo modelo que usé en otros ejemplos anteriores.&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:30955e46-f9ad-4f79-a01b-42bcb25fff5c" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;AjFirstExample&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;First Example using AjGenesis&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Description&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Prefix&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;AjFE&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Prefix&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Domain&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;com.ajlopez&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Domain&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;CompanyName&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;ajlopez&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;CompanyName&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Entities/Customer.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entity &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Source&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Entities/Supplier.xml&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Entities&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Lists&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;List &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;List &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Lists&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Forms&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Form &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Form &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Forms&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Views&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;View &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Customer&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;View &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Entity&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;=&amp;quot;Supplier&amp;quot;&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Views&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Model&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Project&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;El directorio Templates contiene dos conjuntos de archivos .tpl&amp;nbsp;, que son templates AjGenesis. Los de MsSql son usados en la generación de scripts DDL. En el folder CSharp3, hay nuevos templates que generan un LINQ DataContext, y clases simples, como entidades y servicios.&lt;/p&gt;
&lt;h3&gt;Ejecutando el ejemplo&lt;/h3&gt;
&lt;p&gt;El directorio principal del ejemplo hay un archivo de comando:&lt;/p&gt;
&lt;p&gt;&lt;font face="Consolas"&gt;makeajfirstexample.cmd&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;que al ejecutarse, carga el modelo abstracto y el de tecnología en memoria, y&amp;nbsp;ejecuta dos tareas, creando códidog y scripts de generación de base de datos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajfirstexamplenet3cmd.png" alt="" /&gt; 
&lt;p&gt;Lo generado reside en un nuevo directorio Build, con código fuente y scripts para MS SQL: 
&lt;p align="left"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajfirstexamplenet3bld.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El archivo Build\AjFirstExample\CSharp3\Sql\CreateDatabase.sql crea la base y tablas, un fragmento:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:71309bad-5e97-4183-902e-bf846b13c171" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;create&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;database&lt;/span&gt;&lt;span style="color:#000000;"&gt; AjFirstExampleNet3
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;go&lt;/span&gt;&lt;span style="color:#000000;"&gt;

...

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;use&lt;/span&gt;&lt;span style="color:#000000;"&gt; AjFirstExampleNet3
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;go&lt;/span&gt;&lt;span style="color:#000000;"&gt;

...

&lt;/span&gt;&lt;span style="color:#008080;"&gt;--
--&lt;/span&gt;&lt;span style="color:#008080;"&gt;        Entity:        Customer&lt;/span&gt;&lt;span style="color:#008080;"&gt;
--&lt;/span&gt;&lt;span style="color:#008080;"&gt;        Description:    Customer Entity&lt;/span&gt;&lt;span style="color:#008080;"&gt;
--
&lt;/span&gt;&lt;span style="color:#000000;"&gt;

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;exists&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;select&lt;/span&gt;&lt;span style="color:#000000;"&gt; name &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;from&lt;/span&gt;&lt;span style="color:#000000;"&gt; sysobjects 
         &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;where&lt;/span&gt;&lt;span style="color:#000000;"&gt; name &lt;/span&gt;&lt;span style="color:#808080;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Customer&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;and&lt;/span&gt;&lt;span style="color:#000000;"&gt; type &lt;/span&gt;&lt;span style="color:#808080;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;U&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;drop&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;table&lt;/span&gt;&lt;span style="color:#000000;"&gt; Customer
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;go&lt;/span&gt;&lt;span style="color:#000000;"&gt;

&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;create&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;table&lt;/span&gt;&lt;span style="color:#000000;"&gt; Customer (
        &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Id&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;uniqueidentifier&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;not&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt; 
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;CONSTRAINT&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;DF_Customer_id&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;DEFAULT&lt;/span&gt;&lt;span style="color:#000000;"&gt; (&lt;/span&gt;&lt;span style="color:#FF00FF;"&gt;newid&lt;/span&gt;&lt;span style="color:#000000;"&gt;()),    
        &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;"&gt;nvarchar&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#800000;font-weight:bold;"&gt;200&lt;/span&gt;&lt;span style="color:#000000;"&gt;),    
        &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Address&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;"&gt;nvarchar&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#800000;font-weight:bold;"&gt;2048&lt;/span&gt;&lt;span style="color:#000000;"&gt;),    
        &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Notes&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#000000;font-weight:bold;"&gt;nvarchar&lt;/span&gt;&lt;span style="color:#000000;"&gt;(&lt;/span&gt;&lt;span style="color:#800000;font-weight:bold;"&gt;2048&lt;/span&gt;&lt;span style="color:#000000;"&gt;)
 &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;CONSTRAINT&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;PK_Customer&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;PRIMARY&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;KEY&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;CLUSTERED&lt;/span&gt;&lt;span style="color:#000000;"&gt; 
(
    &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;Id&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;ASC&lt;/span&gt;&lt;span style="color:#000000;"&gt;
)&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;WITH&lt;/span&gt;&lt;span style="color:#000000;"&gt; (PAD_INDEX  &lt;/span&gt;&lt;span style="color:#808080;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;OFF&lt;/span&gt;&lt;span style="color:#000000;"&gt;, IGNORE_DUP_KEY &lt;/span&gt;&lt;span style="color:#808080;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;OFF&lt;/span&gt;&lt;span style="color:#000000;"&gt;) 
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;ON&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#FF0000;"&gt;[&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;PRIMARY&lt;/span&gt;&lt;span style="color:#FF0000;"&gt;]&lt;/span&gt;&lt;span style="color:#000000;"&gt;
)
&lt;/span&gt;&lt;span style="color:#0000FF;"&gt;go&lt;/span&gt;&lt;span style="color:#000000;"&gt;

&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p align="left"&gt;La solución puede cargarse directamente en Visual Studio 2008:&lt;/p&gt;
&lt;p align="left"&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajfirstexamplenet3sln.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;La clase AjFirstExampleDataContext.cs es un simple LINQ DataContext:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:ac463baa-7e19-431b-bbba-a80824bcb120" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;partial&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; AjFirstExampleDataContext : 
        System.Data.Linq.DataContext
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; AjFirstExampleDataContext() 
....
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Table&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Customer&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; Customers;
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Table&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Supplier&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; Suppliers;
    }

&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Podríamos reemplazarlo por un DataContext generado por el wizard de Linq To SQL que viene en el Visual Studio. Hay una opción en el modelo de tecnología para especificar qué estrategia usar: o genera un archivo nuestro, o deja al desarrollador poner manualmen luego, al levantar la solución, un DataContext generado por el propio IDE. El resto de las clases funciona igual contra cualquiera de las dos opciones.&lt;/p&gt;
&lt;p&gt;La solución tiene 3 proyectos: datos, servicios y presentación ASP.NET. La página inicial es espartana (ya me conocen, soy desarrollador, no diseñador gráfico... :-)):&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajfirstexamplenet3pag.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Desde la opción de Administration, podemos explorar, agregar, editar y borrar clientes y proveedores:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/ajfirstexamplenet3cus.png" alt="" /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Próximos pasos&lt;/h3&gt;
&lt;p&gt;Quiero convertir otros ejemplos anteriores a estos nuevos templates (el modelo de AjTest es el más desafiante, con relaciones uno a varios y varias entidades). Sería interesante generar páginas ASP.NET MVC, en lugar de ASP.NET plano. Y algunos proyectos adicionales, de infraestructura de testo. Estoy viendo el código de &lt;a href="http://www.codeplex.com/ScrumLite" target="_blank"&gt;ScrumLite&lt;/a&gt; como un ejemplo base a seguir.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;br /&gt;&lt;a href="http://delicious.com/ajlopez"&gt;http://delicious.com/ajlopez&lt;/a&gt;&lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;br /&gt;&lt;a title="http://friendfeed.com/ajlopez" href="http://friendfeed.com/ajlopez"&gt;http://friendfeed.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1649363" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Diez reglas principales en generación de código</title><link>http://msmvps.com/blogs/lopez/archive/2008/08/25/diez-reglas-principales-en-generaci-243-n-de-c-243-digo.aspx</link><pubDate>Mon, 25 Aug 2008 07:38:42 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1645697</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1645697</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/08/25/diez-reglas-principales-en-generaci-243-n-de-c-243-digo.aspx#comments</comments><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;img style="margin:0px 20px 20px 0px;" src="http://www.manning.com/herrington/herrington_cover150.jpg" align="left" alt="" /&gt;Cualquiera&amp;nbsp;puede reconocer en mí a un&amp;nbsp;entusiasta de la generación&amp;nbsp;automática de código,&amp;nbsp;con un agregado: usar&amp;nbsp;un modelo como el punto de partida del proceso.&amp;nbsp;He adoptado esa idea cada semana, practicando &amp;quot;dog fooding&amp;quot;, usando mi&amp;nbsp;propio proyecto de generación de código &lt;a href="http://www.ajlopez.com/ajgenesis" target="_blank"&gt;AjGenesis&lt;/a&gt;. Esta semana, estoy leyendo el libro ya clásico &amp;quot;&lt;a href="http://www.manning.com/herrington/" target="_blank"&gt;Code Generation in Action&lt;/a&gt;&amp;quot;&amp;nbsp;, de Jack Herrington, editado por Manning. Este libro es un &amp;quot;debe ser leído&amp;quot; por cualquiera ineresado en generación de código. Es una muy interesante lectura para desarrolladores: el autor expone un caso a favor del uso de la generación de código, apelando al incremento en calidad y productividad en proyectos de software, incluyendo equipos ágiles.  &lt;p&gt;En el primer capítulo,&amp;nbsp;Herrington lista&amp;nbsp;las reglas &amp;quot;top ten&amp;quot; que quiero comentar en este post. Los párrafos indentados que siguen son extraídos del libro (sección 1.7), seguidos por mis propios comentarios:  &lt;h3&gt;De el debido respeto a código generado a mano&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Ud debe respetar y rechazar el´código manal. Ud. debe respectarlo porque hay casos especiales en el código que son pasados por alto en una inspección somera. Cuando reemplaza código manual por código generado,&amp;nbsp;necesita&amp;nbsp;estar seguro de haber contemplado esos casos especiales. Ud. debe sentirse disgustado con el código manual porque el tiempo de desarrollo es extremadamente valioso, y gastarlo en tareas repetitiva es casi criminal. El objetivo de su generador de código debe ser siempre optimizar el activo más valioso de su organización: la creatividad y el entusiasmo del equipo de desarrollo.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Cierto, la base de la generación de código es hacer fácil el delegar las tareas repetivivas a la máquina. Nosotros tenemos que usar herramientas que hagan más fácil nuestro trabajo:&amp;nbsp;ésa es la razón&amp;nbsp;por la que usamos compiladores hoy en día, en lugar de estar &amp;quot;seteando&amp;quot; los bits en la memoria (o &amp;quot;seteando&amp;quot; los relés en la vieja Eniac a mano). La razón que sustenta&amp;nbsp;la generación de código no es destruir el código manual: su&amp;nbsp; misión es soportarlo.&lt;/p&gt; &lt;h3&gt;Primero escriba a mano&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Ud. debe entender completamente su framework antes de generar código. Idealmente, debería escribir a mano una amplia y significativa cantidad de código con el framework, primero, y luego entonces,&amp;nbsp; usarlo como base para los &amp;quot;templates&amp;quot; de su generador.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Absolutamente de acuerdo. A veces, los nuevos usarios de AjGenesis comienzan a usarlo directamente de los ejemplos. Eso es bueno, pero seria mejor generar un ejemplo usando&amp;nbsp;el framework y la tecnología que tengan que encarar. Si Ud. conoce cómo programar usado&amp;nbsp;Struts/Hibernate, entonces puede separar las variaciones técnicas de lo esencial. Llegado a ese punto, podrá comenzar a escribir los artefactos de generación de código que necesite (templates, tareas).&lt;/p&gt; &lt;h3&gt;Controle el código fuente&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;No puedo dejar de enfatizar la importancia de tener un sistema de control de código robusto. Es crítico para el éxito de un proyecto de generación de código. Si su generador trabaja directamente sobre los archivos de implementación que contiene código generado a mano, asegúrese que tiene el sistema de versionado funcionando para que pueda proteger su trabajo.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Otro camino: si Ud. genera código desde el modelo, incluya en el repositorio de código sólo al modelo. El resto de los artifactos vendrán producidos por el proceso de generación. Con la actual tecnología, no se puede generar TODO la aplicación, pero Ud. puede separar, con cuidad, la parte manual de la generada.&lt;/p&gt; &lt;h3&gt;Tome con cuidado una decisión sobre el lenguaje de implementación&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Las herramientas que use para armar el generador no tienen que ser las&amp;nbsp;mismas que usa para escribir las aplicaciones finales. El problema que el generador está tratando de resolver es completamente diferente del las aplicaciones. Por esa razón, Ud. debe ver al generador como un proyecto independiente y diferente, y elegir sus herramientas de acuerdo a lo que necesita.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Esta es una de las razones por que adopté un nuevo lenguaje (llamado afectuosamente AjBasic) para mi proyecto AjGenesis. Yo quería un lenguaje dinámico que estuviera bajo mi control, para extenderlo en cualquier dirección que el proceso de generación requiera. En uno de mis pruebas iniciales, intenté usar PHP, pero he preferido usar un lenguaje dedicado y pensado para este trabajo, como AjBasic.&lt;/p&gt; &lt;h3&gt;Integre el generador en el proceso de desarrollo&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;El generador es una herramienta para ser usada por ingenieros; entonces, debería encajar claramente en algún punto del proceso de desarrollo. Si es apropiado, puede integrarse en la IDE que use, o en el proceso de build o de check-in en el repositorio de código.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Al haber hecho que el núcleo del AjGenesis sea una librería de clases .NET, pude integrarlo con otras herramientas. Ahora, puedo usarlo desde el NAnt. Una herramienta que se integre a la IDE del Visual Studio o del Eclipse, es una tarea pendiente.&lt;/p&gt; &lt;h3&gt;Incluya advertencias&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Su generador debe siempre dejar advertencias en el código para qu ela gente no vaya y toque ese código. Si se agrega código agregado a mano y se ejecuta de nuevo el proceso de generación, perderemos las modificaciones. No debe culpar a la gente: el que estén usando su herramienta es un gran paso adelante. En cambio, ponga mayores advertencias, y mejore la documentación del generador. Ud. es el emisario de su herramienta.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;En AjGenesis, este problema es atacado por los templates que el usuario escriba. Ud. puede agregar cualquier texto que Ud. quiera, con las advertencias correspondientes: éste es el poder de poder escribir sus propios templates, Ud. tiene la propiedad del código generador, no depende de la herramienta.&lt;/p&gt; &lt;h3&gt;Hágalo amigable&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Sólo porque el generador es una herramienta para programadores no significa que tenga que ser críptico su uso. El generador debe decir al desarrollador lo que está haciendo, y qué archivos ha alterador o creado, y debe manejar los errores con una razonable cuota de decoro. Puede parecer tonto, pero una herramienta que es difícil de usar o que no es amigable será ignorada y sus esfuerzos por promoverla serán en vano.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;El núcleo de AjGenesis es una dll, que puede ser invocada desde una aplicación. Hace años, escribí tareas para invocarlo y ser usado desde el NAnt. Gracias a Jonathan Cisneros, tenemos el AjGenesis Studio, desde el año pasado. He mejorado el código original, y a principios de 2008, agregué el AjGenesis Web Studio, para generar desde una interfaz web. El manejo de errores debe ser mejorado, especialmente para los nuevos usuarios de AjBasic.&lt;/p&gt; &lt;h3&gt;Incluya documentación&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;La buena documentación es un punto a favor de la venta del generador. Su documentación debe ser abarcativa, sin ser intimidante, y cubrir los puntos principales: qué hace el generador, cómo se instala, cómo se ejecuta, y qué archivos afecta.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Actualmente, éste es un punto no bien cubierto por AjGenesis. Pero a cambio, hay varios posts explicando el proceso y los ejemplos (&lt;a href="http://ajlopez.wordpress.com/category/ajgenesis" target="_blank"&gt;AjGenesis posts&lt;/a&gt;) (&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx" target="_blank"&gt;AjGenesis posts en Español&lt;/a&gt;). Usuarios de la herramienta están comenzando a escribir también (ver los posts de &lt;a href="http://carlossantos.wordpress.com/tag/ajgenesis/" target="_blank"&gt;Carlos Marcelo Santos&lt;/a&gt;). Hay una lista de correo en español donde los usuarios pueden discutir sob ela herramienta&amp;nbsp;y su uso (&lt;a href="http://groups.google.com/group/codegeneration" target="_blank"&gt;Code Generation group&lt;/a&gt;). Y en la&amp;nbsp;&lt;a href="http://www.codeplex.com/ajgenesis"&gt;la página del proyecto en&amp;nbsp;Codeplex&lt;/a&gt;, hay ejemplo para generar Java, .NET, y PHP, varios usando el mismo modelo (una prueba ácida para un generador).&lt;/p&gt; &lt;h3&gt;Recuerde que la generación es un tema cultural&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Uducar a sus colegas con documentación, seminarios, y encuentros uno a uno es crítico para instalar y usar su generador. La gente es escéptica a las nuevas cosas, y un buen programador es el doble de escéptico que una persona promedio. Ud. necesita romper con esa resistencia y dudas, y emfatizar que el generador que ha diseñado los beneficiará.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Yo doy de tres a cuatro charlas por año, sólo dedicadas a explicar la herramienta y su potencial. Adicionalmente, la explico en casi cada curso que doy (de Java, .NET, PHP o de software en general). Pero para ser adoptada por una compañía o en un proyecto, un usuario debe&amp;nbsp;tomar el cargo de campeón del producto. No es fácil elevar el nivel de&amp;nbsp;abstracción, escribir el modelo y sus transformaciones, en el&amp;nbsp;medio del trabajo del día a día.&lt;/p&gt; &lt;h3&gt;Mantenga el generador&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;A menos que el generador sea una medida temporaria, necesitará ser mantenido en el largo palzo. Si el generador maneja una cantidad grande de código, trátelo como Ud. trataría a un ingeniero manteniendo ese mismo código. Su presupuesto debe incluir tiempo y dinero dedicado a mantener y actualizar este recurso.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;AjGenesis no es parte de las &amp;quot;cosas&amp;quot; a mantener. Estas son los templates y tareas que usará en su trabajo. Si Ud. adopta la herramienta para generar aplicaciones, digamos, .NET, Ud. tiene que cambiar e ir mejorando los templates cuando nuevas tecnologías aparezcan&amp;nbsp;(LINQ, ASP.NET MVC....). Y cuando Ud. gana experiencia, Ud. tiene que mejorar el mismo modelo, si descubre nuevas maneras de representar las líneas de producto en las que su compañía se interesa.&lt;/p&gt; &lt;p&gt;Yo podría agregar algunos puntos más:&lt;/p&gt; &lt;p&gt;- El código generado debe ser de la clase de código que Ud. mismo hubiera producido, y del que se sienta orgulloso. La herramienta no debe dictar la forma y la apariencia de su código. Ud. debe estar a cargo.&lt;/p&gt; &lt;p&gt;- El uso de un modelo eleva el nivel de abstracción que manejamos. Esta estrategia separa la paja del trigo, pone los detalles técnicos en el lugar que merecen: lo importante es el modelo.&lt;/p&gt; &lt;p&gt;Bueno, bastante por ahora. Como pueden darse cuenta, la generación de código es un tema que me apasiona. No es la bala de plata. Pero es un arma que quisiera tener, por si la necesito.&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1645697" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>"Ver la luz" con generación de código y AjGenesis</title><link>http://msmvps.com/blogs/lopez/archive/2008/06/10/quot-ver-la-luz-quot-con-generaci-243-n-de-c-243-digo-y-ajgenesis.aspx</link><pubDate>Tue, 10 Jun 2008 14:02:59 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1633619</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1633619</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/06/10/quot-ver-la-luz-quot-con-generaci-243-n-de-c-243-digo-y-ajgenesis.aspx#comments</comments><description>&lt;p&gt;Ayer dí una charla gratuita sobre generación de código, usando &lt;a href="http://www.ajlopez.com/ajgenesis" target="_blank"&gt;AjGenesis&lt;/a&gt;. Espero haber transmitido la idea de que es más que generación de código, y que va más allá de la tecnología actual.&lt;/p&gt; &lt;p&gt;Quisiera enumerar algunos posts relacionados con el tema, y comentarlos, así como enumerar enlaces y recursos.&lt;/p&gt; &lt;h3&gt;Posts sobre generación de código&lt;/h3&gt; &lt;p&gt;&lt;a title="Sobre la generaci&amp;oacute;n de c&amp;oacute;digo" href="http://msmvps.com/blogs/lopez/archive/2007/08/02/sobre-la-generaci-243-n-de-c-243-digo.aspx"&gt;Sobre la generación de código&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Este es el primer post a leer. Vemos ahí que el cambio de tecnología es una constante en la historia de desarrollo de software, y que no se ve en el horizonte una unificación de nada, ni de lenguajes ni de plataformas. Cada año que pasa, sabemos más de hacer sistemas, pero curiosamente, cada sistema nuevo necesita más codigo que el anterior, en general. Aún usando tecnologías que nos alivian el trabajo, por ejemplo, algún ORM (Object Relational Mapper), si la tecnología triunfa, el propio mercado nos lleva a hacer sistemas más complejos y grandes, y lo que ahorramos en código a escribir, luego lo perdemos en la mayor complejidad de lo sistemas que tenemos a nuestro alcance construir.&lt;/p&gt; &lt;p&gt;También se enumeran otras alternativas a la generación de código, y sus problemas. Las herramientas CASE son muy rígidas, o generales o abarcativas, así como UML y otras iniciativas. Lo que necesitamos son modelos específicos de nuestro dominio, y poder generar lo que querramos, de la forma que nos convenga. De ahí la necesidad de contar con un generador de código que no esté orientado a una tecnología a generar en particular, que sea de código abierto, y que genere lo que nosotros le indicamos, no lo que los autores de la herramienta quieren o pensaron inicialmente.&lt;/p&gt; &lt;p&gt;El usar frameworks propietarios, quedarse en una sola tecnología, tratar de generar todo en runtime apelando a metadata, o generar código desde XML aplicando transformaciones XSLT, son alternativas que creo que son inferiores o más complejas, como se explica en ese post.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Generando C&amp;oacute;digo- Hello World con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2006/11/19/generando-c-digo-hello-world-con-ajgenesis.aspx"&gt;Generando Código- Hello World con AjGenesis&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Esta es la &amp;quot;prueba ácida&amp;quot; de todo generador de código. Si una herramienta de ese tipo no nos ayuda a crear programas &amp;quot;Hola mundo&amp;quot;, con variantes, en distintas tecnologías, entonces no es lo bastante flexible. AjGenesis hace hincapié en la flexibilidad, la adaptibilidad a lo que Uds quieran producir, sin atarlos a una forma o metadata en particular.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Generando aplicaciones con AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2007/06/25/generando-aplicaciones-con-ajgenesis.aspx"&gt;Generando aplicaciones con AjGenesis&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Un post algo viejo, pero que muestra cómo se pueden generar aplicaciones no triviales con esta herramienta.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="AjGenesis- Modelo generado desde los assemblies" href="http://msmvps.com/blogs/lopez/archive/2007/11/27/ajgenesis-modelo-generado-desde-los-assemblies.aspx"&gt;AjGenesis- Modelo generado desde los assemblies&lt;/a&gt;&lt;br /&gt;&lt;a title="AjGenesis- Modelo desde la Base de Datos" href="http://msmvps.com/blogs/lopez/archive/2007/11/25/ajgenesis-modelo-desde-la-base-de-datos.aspx"&gt;AjGenesis- Modelo desde la Base de Datos&lt;/a&gt;&lt;br /&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Posts sobre cómo el modelo puede partir de otras fuentes, cualquiera que Uds. vean que sea conveniente. Luego, la propia herramienta puede mejorar, completar el modelo, hacer inferencias, o Uds. mismos completarlos, por ejemplo, si el modelo de base de datos no es lo bastante rico para darnos algo de semántica sobre el sistema que tenemos entre manos.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Generando c&amp;oacute;digo para NHibernate (Parte 3)" href="http://msmvps.com/blogs/lopez/archive/2007/10/29/generando-c-243-digo-para-nhibernate-parte-3.aspx"&gt;Generando código para NHibernate (Parte 3)&lt;/a&gt;&lt;br /&gt;&lt;a title="Generando c&amp;oacute;digo para NHibernate (Parte 2)" href="http://msmvps.com/blogs/lopez/archive/2007/09/25/generando-c-243-digo-para-nhibernate-parte-2.aspx"&gt;Generando código para NHibernate (Parte 2)&lt;/a&gt;&lt;br /&gt;&lt;a title="Generando c&amp;oacute;digo para NHibernate (Parte 1)" href="http://msmvps.com/blogs/lopez/archive/2007/08/05/generando-c-243-digo-para-nhibernate-parte-1.aspx"&gt;Generando código para NHibernate (Parte 1)&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Para ver que pueden usar AjGenesis para facilitar el desarrollo usando alguna librería reconocida por la comunidad, pueden leer esta serie de enlaces, donde gracias a una idea de Omar&amp;nbsp;del valle Rodríguez, se desarrollaron templates para usar NHibernate, y generar hasta una capa de presentación web para probar lo generado.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Hacia el AjGenesis Recipes" href="http://msmvps.com/blogs/lopez/archive/2007/11/20/hacia-el-ajgenesis-recipes.aspx"&gt;Hacia el AjGenesis Recipes&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Es un trabajo en progreso, para incorporar interacción con el usuario durante el proceso de generación de código.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Usando AjGenesis y NAnt" href="http://msmvps.com/blogs/lopez/archive/2007/11/01/usando-ajgenesis-y-nant.aspx"&gt;Usando AjGenesis y NAnt&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Explicación y enlaces para usar AjGenesis desde NAnt. Si alguien necesita una interfaz gráfica NAnt-GUI, pueden bajarla desde &lt;a title="NAnt-GUI" href="http://groups.google.com/group/codegeneration/t/2aef426f02370d1"&gt;NAnt-GUI&lt;/a&gt;&amp;nbsp;(preparado por Carlos Marcelo Santos, del &lt;a href="http://groups.google.com/group/codegeneration" target="_blank"&gt;grupo de generación de código&lt;/a&gt;)&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Genesis Studio- una IDE para AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2007/12/24/genesis-studio-una-ide-para-ajgenesis.aspx"&gt;Genesis Studio- una IDE para AjGenesis&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;No todo lo tienen que hacer desde la línea de comando, o desde el NAnt/NAnt-GUI. El bueno de Jonathan Cisneros desarrolló esta herramienta WinForm, con sintaxis de color y muchas mejoras en la experiencia de usuario, que pueden bajar desde:&lt;/p&gt; &lt;p&gt;&lt;a title="http://www.codeplex.com/ajgenesisstudio" href="http://www.codeplex.com/ajgenesisstudio"&gt;http://www.codeplex.com/ajgenesisstudio&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Preservando c&amp;oacute;digo en AjGenesis" href="http://msmvps.com/blogs/lopez/archive/2007/11/11/preservando-c-243-digo-en-ajgenesis.aspx"&gt;Preservando código en AjGenesis&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Si necesitan generar código, pero luego modificarlo, pueden usar algunas capacidades de AjGenesis para delimitar qué parte regenerar y cuales conservan.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;&lt;a title="Code Generation as a Service" href="http://msmvps.com/blogs/lopez/archive/2008/04/03/code-generation-as-a-service.aspx"&gt;Code Generation as a Service&lt;/a&gt;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;La última adición al AjGenesis: ahora pueden generar código usando una interfaz web. Esto permite que&amp;nbsp;ya sea en Internet, o desde la intranet de su empresa, puedan generar código controlado, que cumpla con los estándares que se hayan adoptado.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Más posts sobre AjGenesis en&lt;/p&gt; &lt;p&gt;&lt;a title="AjGenesis" href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx"&gt;AjGenesis&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Si necesitan pasarle información a alguien que no maneja el español, pueden probar con mis artículos en &amp;quot;Anglish&amp;quot; (Angel&amp;#39;s English):&lt;/p&gt; &lt;p&gt;&lt;a title="http://ajlopez.wordpress.com/category/ajgenesis" href="http://ajlopez.wordpress.com/category/ajgenesis"&gt;http://ajlopez.wordpress.com/category/ajgenesis&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Enlaces&lt;/h3&gt; &lt;p&gt;EL sitio sobre generación de código es&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codegeneration.net"&gt;http://www.codegeneration.net&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Ahí encontraran comentarios, herramientas, preguntas frecuentes sobre generación de código en general. Tienen una base de datos de herramientas publicadas. Hay enlaces sobre generación de código para distintas tecnologías, como Java, .NET, PHP y también temas de MDA (Model-Driven Architecture).&lt;/p&gt; &lt;p&gt;Otros enlaces que tratamos en las charlas son:&lt;/p&gt; &lt;p&gt;&lt;a title="CodeSmith Tools - The best .NET template based source code" href="http://www.codesmithtools.com/"&gt;CodeSmith Tools&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="MyGeneration Software" href="http://www.mygenerationsoftware.com/"&gt;MyGeneration Software&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a title="AndroMDA.org - Home" href="http://www.andromda.org/"&gt;AndroMDA.org - Home&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Mantengo todo tipo de enlaces relativos a generación de código en&lt;/p&gt; &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/codegeneration"&gt;http://del.icio.us/ajlopez/codegeneration&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;Lista de correo sobre generación de código&lt;/h3&gt; &lt;p&gt;Existe un Google Group que se puede consultar por email, en español, dedicado a la generación de código. Ahí, además de otros temas, se trata de generación de código con AjGenesis, la generación de templates. En los archivos del grupo se publican ejemplos armados por los miembros.&lt;/p&gt; &lt;p&gt;Pueden ver los mensajes y suscribirse, en:&lt;/p&gt; &lt;p&gt;&lt;a title="http://groups.google.com/group/codegeneration" href="http://groups.google.com/group/codegeneration"&gt;http://groups.google.com/group/codegeneration&lt;/a&gt;&lt;/p&gt; &lt;h3&gt;Conclusión&lt;/h3&gt; &lt;p&gt;Espero que quede claro que lo importante es usar generación de código como solución pragmática, pero basado en la abstracción de un modelo. Hacer el ejercicio de abstracción de generar un modelo adecuado para lo que necesitemos, es un &amp;quot;must&amp;quot; que me parece el primer paso para separarnos de los problemas de cambios en las tecnologías, herramientas y plataformas.&lt;/p&gt; &lt;p&gt;Luego, el modelo debe ser de libre definición. Y el texto o código generado, también: debe ser el tipo de texto o código que hubiéramos generado nosotros mismos. Finalmente, la herramienta de generación de código tiene que estar disponible en código totalmente abierto, para que se pueda extender, entender o usar de la forma que querramos.&lt;/p&gt; &lt;p&gt;Tengo que escribir más sobre la importancia del modelo, y que pueden hacer el suyo propio: no hay modelo fijo, pueden partir desde la base de datos, desde los archivos XML de los ejemplos, o desde donde quieran. También tengo que escribir sobre la posibilidad de hacer modelos que se deriven de otros modelos. Y escribir haciendo énfasis en que lo que construimos, en realidad, es un sistema experto. De ahí, que desde el principio, incorporé un lenguaje de programación que puede tomar decisiones, completar y modificar el modelo.&lt;/p&gt; &lt;p&gt;Como ven, con AjGenesis, ¡sky is the limit! :-)&lt;/p&gt; &lt;p&gt;Nos leemos!&lt;/p&gt; &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1633619" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/PHP/default.aspx">PHP</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Arquitectura/default.aspx">Arquitectura</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/NHibernate/default.aspx">NHibernate</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C_26002300_243_3B00_digo+Abierto/default.aspx">C&amp;#243;digo Abierto</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/VB.NET/default.aspx">VB.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item><item><title>Charla gratuita sobre generación de código</title><link>http://msmvps.com/blogs/lopez/archive/2008/06/06/charla-gratuita-sobre-generaci-243-n-de-c-243-digo.aspx</link><pubDate>Fri, 06 Jun 2008 13:48:42 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1632327</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1632327</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/06/06/charla-gratuita-sobre-generaci-243-n-de-c-243-digo.aspx#comments</comments><description>&lt;p&gt;Casi todos los cursos y charlas que doy, termino mencionando generación de código, desde un modelo, como una solución pragmática a varios problemas que tenemos al desarrollar sistemas. El lunes que viene, doy una charla gratuita sobre el tema, en el &lt;a href="http://www.clubdeprogramadores.com" target="_blank"&gt;Club de Programadores&lt;/a&gt;, acá en Buenos Aires.&lt;/p&gt; &lt;p&gt;Más información e inscripción:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.clubdeprogramadores.com/cursos/CursoMuestra.php?Id=439" target="_blank"&gt;Curso Generacion de Código&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Objetivos&lt;/strong&gt;&lt;br /&gt;Durante la charla, examineremos el concepto de modelo independiente de la plataforma de un sistema, y mediante tecnologias de templates, generaremos codigo para gran parte de una aplicacion, en distintas tecnologias, como PHP, Java con JSP, .NET con ASP.NET, contra MySql o SQL Server, usando distintas estrategias de persistencia, como procedimientos almacenados o NHibernate. Todo basado en un mismo modelo, con distintas plantillas de generacion de codigo, manejados desde el proyecto de codigo abierto &lt;a href="http://www.ajlopez.com/ajgenesis" target="_blank"&gt;AjGenesis&lt;/a&gt;.  &lt;p&gt;&lt;strong&gt;Plan de Estudio&lt;/strong&gt;&lt;br /&gt;- Modelo independiente de la plataforma&lt;br /&gt;- Generacion de artefactos de texto con logica y plantillas definibles por cada usuario (no produce algo fijo, sino codigo como el que hubiéramos producido en nuestro equipo de programacion)&lt;br /&gt;- Capacidad de ejecutar varias tareas adicionales (compilacion, instalacion en la base, ....)&lt;br /&gt;- Organizacion de esa tareas de generacion y adicionales en forma automatica y repetible&lt;br /&gt;- Adaptacion a varias tecnologias destino  &lt;p&gt;Lo mío es un apostolado, espero que puedan &amp;quot;ver la luz&amp;quot; .... :-) ;-) &lt;p&gt;Hay bastante sobre el tema publicado en este blog en: &lt;p&gt;&lt;a title="AjGenesis" href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx"&gt;AjGenesis&lt;/a&gt;&lt;br /&gt;&lt;a title="Generaci&amp;oacute;n de C&amp;oacute;digo" href="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx"&gt;Generación de Código&lt;/a&gt; &lt;p&gt;Artículo inicial a leer  &lt;p&gt;&lt;a title="Sobre la generaci&amp;oacute;n de c&amp;oacute;digo" href="http://msmvps.com/blogs/lopez/archive/2007/08/02/sobre-la-generaci-243-n-de-c-243-digo.aspx"&gt;Sobre la generación de código&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Algunos enlaces a recursos en la web: &lt;p&gt;&lt;a href="http://del.icio.us/ajlopez/codegeneration"&gt;http://del.icio.us/ajlopez/codegeneration&lt;/a&gt; &lt;p&gt;Nos leemos! &lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/"&gt;http://www.ajlopez.com/&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1632327" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Java/default.aspx">Java</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/PHP/default.aspx">PHP</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Generaci_26002300_243_3B00_n+de+C_26002300_243_3B00_digo/default.aspx">Generaci&amp;#243;n de C&amp;#243;digo</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx">AjGenesis</category></item></channel></rss>